! TJOI2018智力竞赛

题意:给你一个有向图,用n条路径覆盖(点可重复),使得未被覆盖的点权值最小最大

思考:

先缩点(不过貌似本题无环),变有向无环图(不一定连通)

二分+网络流最小路径覆盖?

查了查发现最小路径覆盖不可重点,此题是可重点的最小路径覆盖(需保证无环)

怎么又去看题解了?!

floyed求一下传递闭包即可转化
时间复杂度O(m3+m2log)

#include<bits/stdc++.h>
using namespace std;
inline int read(){
	int x=0,f=1;char c=getchar();
	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
	return f==1?x:-x;
}
const int N=504;
int n,m,val[N],vis[N],b[N],mat[N],a[N][N];
inline bool comp(int x,int y){
	return val[x]<val[y];
}
bool dfs(int x,int mid){
	for(int i=1,v;i<=mid;i++){
		v=b[i];
		if(a[x][v]&&!vis[v]){
			vis[v]=1;
			if(!mat[v]||dfs(mat[v],mid)){mat[v]=x;return 1;}
		}
	}
	return 0;
}
int main(){
	m=read()+1;n=read();
	for(int i=1,k;i<=n;i++){
		val[i]=read();
		k=read();
		while(k--)a[i][read()]=1;
		b[i]=i;
	}
	for(int k=1;k<=n;k++)
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++)
				a[i][j]|=a[i][k]&a[k][j];
	sort(b+1,b+n+1,comp);
	int l=0,r=n,mid,path;
	while(l<r){
		int mid=l+r+1>>1;
		path=mid;
		memset(mat,0,sizeof(mat));
		for(int i=1;i<=mid;i++){
			memset(vis,0,sizeof(vis));
			if(dfs(b[i],mid))path--;
		}
		if(path<=m)l=mid;
		else r=mid-1;
	}
	if(r==n)puts("AK");
	else cout<<val[b[r+1]]<<"\n"; 
	return (0-0);
}
posted @ 2020-04-02 15:36  starusc  阅读(122)  评论(0)    收藏  举报