【BZOJ1143】【CTSC2008】祭祀river 傳遞閉包、最大點獨立集(網路流寫的)
阿新 • • 發佈:2019-01-28
#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; }