BZOJ 2718/1533 Violet 4 毕业旅行

2718: [Violet 4]毕业旅行

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 676  Solved: 391
[Submit][Status][Discuss]

Description

Input

Output

最多可选多少景点

Sample Input

7 6
1 2
2 3
5 4
4 3
3 6
6 7

Sample Output

2

HINT

 

 

Source

 
用floyed传递背包求出那两个点之间可以到达
剩下的不就是在一个二分图中求出最大独立集么么?最大独立集=总点数-二分图最大匹配数(也就是最小点覆盖)
dinic跑二分图最大匹配数的复杂度是O(n*sqrt(n))
#include <bits/stdc++.h>
#define ll long long
#define inf 1e9+10
using namespace std;
inline int read(){
	int x=0;int f=1;char ch=getchar();
	while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
	while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
const int MAXN=5e4+10;
struct node{
	int y,next,flow,back;
}e[MAXN];
int linkk[MAXN],len,n,head,tail,q[MAXN],level[1000],s,t,v[210][210],m;
inline void insert(int x,int y,int f){
	e[++len].y=y;e[len].next=linkk[x];linkk[x]=len;e[len].back=len+1;e[len].flow=f;
	e[++len].y=x;e[len].next=linkk[y];linkk[y]=len;e[len].back=len-1;e[len].flow=0;
}
inline bool getlevel(){
	head=tail=0;
	memset(level,-1,sizeof(level));
	q[++tail]=s;level[s]=0;
	while(head<tail){
		int tn=q[++head];
		for(int i=linkk[tn];i;i=e[i].next){
			if(e[i].flow&&level[e[i].y]==-1){
				level[e[i].y]=level[tn]+1;
				q[++tail]=e[i].y;
			}
		}
	}
	return level[t]>=0;
}
inline int getmaxflow(int x,int flow){
	if(x==t) return flow;
	int f=0,d;
	for(int i=linkk[x];i;i=e[i].next){
		if(level[e[i].y]==level[x]+1&&e[i].flow){
			if(d=getmaxflow(e[i].y,min(flow-f,e[i].flow))){
				e[i].flow-=d;f+=d;e[e[i].back].flow+=d;
				if(f==flow) return f;
			}
		}
	}
	if(f==0) level[x]=-1;
	return f;
}
inline int dinic(){
	int ans=0,d;
	while(getlevel()){
		while(d=getmaxflow(s,inf)) ans+=d;
	}
	return ans;
}
void build(){
	s=0,t=2*n+1;
	for(int k=1;k<=n;k++){
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++){
				v[i][j]|=(v[i][k]&v[k][j]);
			}
		}
	}
	for(int i=1;i<=n;i++){
		insert(s,i,1);insert(i+n,t,1);
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			if(v[i][j]) insert(i,j+n,inf);
		}
	}
}
int main(){
	n=read();m=read();
	for(int i=1;i<=m;i++){
		int x=read();int y=read();
		v[x][y]=1;
	}
	build();
	printf("%d\n",n-dinic());
	return 0;
}

  

posted @ 2018-05-01 11:38  zhangenming  阅读(258)  评论(0编辑  收藏  举报