[bzoj1143][CTSC2008]祭祀
题意:给定一个n个点m条边的有向无环图,你要选出最多的点,并且满足任意两点之间都不存在通路。2)输出每个点选了它之后还是否有最优解。 n<=100 m<=1000
题解:每个点拆两个点,把每个点向它能走到点连边,然后最小割/二分图匹配。
这题想了好久,后来想出这个模型感觉没问题.....
第二个问貌似把每个点都强行不割跑一遍应该不会T吧.....
#include<iostream> #include<cstdio> #include<queue> #include<cstring> #define S 0 #define T 201 #define INF 2000000000 using namespace std; inline int read() { int x = 0 , f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar();} while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();} return x * f; } int mark[T+5]; int head[T+5],cnt=1,n,m,ans,cc=0,thead[T+5],q[T+5],top,d[T+5]; struct edge{ int to,next,w; }e[T*T+5]; struct tedge{ int to,next; }e2[1005]; inline void ins(int f,int t){e2[++cc]=(tedge){t,thead[f]};thead[f]=cc;} inline void ins(int f,int t,int w) { e[++cnt]=(edge){t,head[f],w};head[f]=cnt; e[++cnt]=(edge){f,head[t],0};head[t]=cnt; } void build(int x,int from) { if(mark[x]!=from&&x!=from) ins(from,x+n,INF),mark[x]=from; for(int i=thead[x];i;i=e2[i].next) if(mark[e2[i].to]!=from) build(e2[i].to,from); } int dfs(int x,int f) { if(x==T)return f; int used=0; for(int i=head[x];i;i=e[i].next) if(e[i].w&&d[e[i].to]==d[x]+1) { int w=dfs(e[i].to,min(f-used,e[i].w)); used+=w;e[i].w-=w;e[i^1].w+=w; if(used==f)return f; } return used; } bool bfs() { memset(d,0,sizeof(d));int i,j; for(d[q[i=top=0]=S]=1;i<=top;++i) for(int j=head[q[i]];j;j=e[j].next) if(e[j].w&&!d[e[j].to]) d[q[++top]=e[j].to]=d[q[i]]+1; return d[T]; } int main() { ans=n=read();m=read(); for(int i=1;i<=m;i++) { int x=read(),y=read(); ins(y,x); } for(int i=1;i<=n;i++)build(i,i); for(int i=1;i<=n;i++)ins(S,i,1),ins(i+n,T,1); while(bfs())ans-=dfs(S,INF); cout<<ans; return 0; }
FallDream代表秋之国向您问好!
欢迎您来我的博客www.cnblogs.com/FallDream