在建图的时候对原图进行加边 建立一个超级源点~
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn=1014; const int maxm=10014; const int inf=1e9; struct edge { int u; int v; int w; }Edge[maxm]; int pre[maxn]; int id[maxn]; int visit[maxn]; int in[maxn]; int N,M; int root; int pos; int num; void add (int u,int v,int w) { Edge[num].u=u; Edge[num].v=v; Edge[num++].w=w; } int solve () { int ans=0; while (1) { for (int i=0;i<N;i++) in[i]=inf; for (int i=0;i<num;i++) { int u=Edge[i].u; int v=Edge[i].v; if (Edge[i].w<in[v]&&u!=v) { pre[v]=u; in[v]=Edge[i].w; if (u==root) pos=i; } } for (int i=0;i<N;i++) { if (i!=root&&in[i]==inf) return -1; } int tn=0; memset(id,-1,sizeof(id)); memset(visit,-1,sizeof(visit)); in[root]=0; for (int i=0;i<N;i++) { ans+=in[i]; int v=i; while (visit[v]!=i&&id[v]==-1&&v!=root) { visit[v]=i; v=pre[v]; } if (v!=root&&id[v]==-1) { for (int u=pre[v];u!=v;u=pre[u]) id[u]=tn; id[v]=tn++; } } if (tn==0) break; for (int i=0;i<N;i++) { if (id[i]==-1) id[i]=tn++; } for (int i=0;i<num;i++) { int v=Edge[i].v; Edge[i].u=id[Edge[i].u]; Edge[i].v=id[Edge[i].v]; if (Edge[i].u!=Edge[i].v) Edge[i].w-=in[v]; } N=tn; root=id[root]; } return ans; } int main () { while (~scanf("%d%d",&N,&M)) { int sum=0; num=0; for (int i=0;i<M;i++) { int u,v,w; scanf ("%d %d %d",&u,&v,&w); sum+=w; add(u,v,w); } sum++; for (int i=0;i<N;i++) { add(N,i,sum); } N++; root=N-1; int ans=solve(); if (ans==-1||ans>=2*sum) { printf ("impossible "); } else printf ("%d %d ",ans-sum,pos-M); printf (" "); } return 0; }