poj 2987 最大闭合子图
思路:
这题考的是最大闭权图。只要知道怎么求最大闭权图就知道怎么做。但好像有点卡模版,要高效的模版才行。
#include <iostream> #include <stdio.h> #include <string.h> #define Maxn 6010 #define Maxm 200000 #define LL __int64 #define Abs(a) (a)>0?(a):(-a) using namespace std; struct Edge{ int from,to,next; LL val; }edge[Maxm]; LL value[Maxn],inf=0; int index[Maxn],work[Maxn],dis[Maxn],q[Maxn],e,vi[Maxn]; inline void addedge(int from,int to,LL val)//有向边 { edge[e].from=from; edge[e].to=to; edge[e].val=val; edge[e].next=index[from]; index[from]=e++; edge[e].from=to; edge[e].to=from; edge[e].val=0; edge[e].next=index[to]; index[to]=e++; } void init() { e=0; memset(index,-1,sizeof(index)); memset(vi,0,sizeof(vi)); inf=0; } void add(int u,int v,LL c) { edge[e].to=v;edge[e].val=c;edge[e].next=index[u];index[u]=e++; edge[e].to=u;edge[e].val=0;edge[e].next=index[v];index[v]=e++; } void DFS(int u) { vi[u]=1; int i,v; for(i=index[u];i!=-1;i=edge[i].next) if(edge[i].val&&!vi[edge[i].to]) DFS(edge[i].to); } int bfs(int S,int T) { int rear=0; memset(dis,-1,sizeof(dis)); dis[S]=0;q[rear++]=S; for(int i=0;i<rear;i++) { for(int j=index[q[i]];j!=-1;j=edge[j].next) { if(edge[j].val&&dis[edge[j].to]==-1) { dis[edge[j].to]=dis[q[i]]+1; q[rear++]=edge[j].to; if(edge[j].to==T) return 1; } } } return 0; } LL dfs(int cur,LL a,int T) { if(cur==T) return a; for(int &i=work[cur];i!=-1;i=edge[i].next) { if(edge[i].val&&dis[edge[i].to]==dis[cur]+1) { int t=dfs(edge[i].to,min(a,edge[i].val),T); if(t) { edge[i].val-=t; edge[i^1].val+=t; return t; } } } return 0; } LL Dinic(int S,int T) { LL ans=0; while(bfs(S,T)) { memcpy(work,index,sizeof(index)); while(int t=dfs(S,inf,T)) ans+=t; } return ans; } int main() { int n,m,i,a,b; LL sum=0; scanf("%d%d",&n,&m); init(); for(i=1;i<=n;i++) { scanf("%I64d",value+i); if(value[i]>0) { sum+=value[i]; addedge(0,i,value[i]); } else addedge(i,n+1,-value[i]); inf+=Abs(value[i]); } inf++; for(i=1;i<=m;i++) { scanf("%d%d",&a,&b); addedge(a,b,inf); } LL ans=Dinic(0,n+1);//起始点和结束点 //DFS(0);//寻找S集合 int num=0; for(i=1;i<=n;i++) if(dis[i]>=0) num++; printf("%d %I64d\n",num,sum-ans); return 0; }