#include <stdio.h> int main() { puts("转载请注明出处谢谢"); puts("http://blog.csdn.net/vmurder/article/details/43225427"); }
题意:那个图不要看,给的没错,是有向无环图(拓扑)
题解:
对于每两点,都有一个关系————>如果传递闭包后a能到b,那么两者只能选一个。
完事了。
代码:
#include <queue> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define N 305 #define M 25000 #define inf 0x3f3f3f3f using namespace std; struct KSD { int v,len,next; }e[M]; int head[N],cnt; inline void add(int u,int v,int len) { e[++cnt].v=v; e[cnt].len=len; e[cnt].next=head[u]; head[u]=cnt; } int s,t,d[N]; queue<int>q; bool bfs() { while(!q.empty())q.pop(); memset(d,0,sizeof d); q.push(s),d[s]=1; int i,u,v; while(!q.empty()) { u=q.front(),q.pop(); for(i=head[u];i;i=e[i].next) { v=e[i].v; if(!d[v=e[i].v]&&e[i].len) { d[v]=d[u]+1; if(v==t)return true; q.push(v); } } } return false; } int dinic(int x,int flow) { if(x==t)return flow; int remain=flow,i,v,k; for(i=head[x];i&&remain;i=e[i].next) { if(d[v=e[i].v]==d[x]+1&&e[i].len) { k=dinic(v,min(remain,e[i].len)); if(!k)d[v]=0; e[i].len-=k,e[i^1].len+=k; remain-=k; } } return flow-remain; } int n,m,maxflow; bool map[N][N]; void build() { int i,j,k; int x,y; scanf("%d%d",&n,&m); cnt=1; s=n*2+1,t=n*2+2; for(i=1;i<=n;i++)add(s,i,1),add(i,s,0); for(i=1;i<=n;i++)add(i+n,t,1),add(t,i+n,0); while(m--) { scanf("%d%d",&x,&y); map[x][y]=1; } for(k=1;k<=n;k++)for(i=1;i<=n;i++)for(j=1;j<=n;j++)map[i][j]|=(map[i][k]&map[k][j]); for(i=1;i<=n;i++)for(j=1;j<=n;j++)if(i!=j&&map[i][j])add(i,j+n,1),add(j+n,i,0); maxflow=n; } int main() { freopen("test.in","r",stdin); build(); while(bfs())maxflow-=dinic(s,inf); printf("%d\n",maxflow); return 0; }