POJ 3068 "Shortest" pair of paths | 最小费用最大流
题目:
给一个有向带权图,问从0到n-1存不存在两条路径保证不存在公共点
若存在输出最小权值和
题解:
先把点编号都++
S向1连权值为0,容量为2,n向T连权值为0,容量为2的点
原始图中每条边(u,v)从u向v连权值为边权,容量为1的点
如果最大流为2就输出最小费用
否则不存在
#include<cstdio> #include<algorithm> #include<cstring> #include<queue> #define N 200100 #define INF 100000000 using namespace std; int ecnt=1,vis[N],dist[N],n,m,S,T,ans,head[N],Case; deque <int> q; struct adj { int nxt,v,w,c; }e[N]; inline void add(int u,int v,int w,int c) { e[++ecnt].v=v,e[ecnt].w=w,e[ecnt].c=c,e[ecnt].nxt=head[u],head[u]=ecnt; e[++ecnt].v=u,e[ecnt].w=0,e[ecnt].c=-c,e[ecnt].nxt=head[v],head[v]=ecnt; } inline int spfa(int s,int t) { int v; memset(vis,0,sizeof(vis)); for (int i=s;i<=t;i++) dist[i]=INF; dist[t]=0,vis[t]=1; q.push_back(t); while (!q.empty()) { int u=q.front();q.pop_front(); for (int i=head[u];i;i=e[i].nxt) if (e[i^1].w>0 && dist[v=e[i].v]>dist[u]-e[i].c) { dist[v]=dist[u]-e[i].c; if (!vis[v]) { vis[v]=1; if (!q.empty() && dist[v]<dist[q.front()]) q.push_front(v); else q.push_back(v); } } vis[u]=0; } return dist[s]<INF; } inline int dfs(int x,int flow) { if (x==T) return vis[T]=1,flow; int used=0,tmp,v; vis[x]=1; for (int i=head[x];i;i=e[i].nxt) if (!vis[v=e[i].v] && e[i].w>0 && dist[x]-e[i].c==dist[v]) { tmp=dfs(v,min(e[i].w,flow-used)); if (tmp>0) ans+=tmp*e[i].c,e[i].w-=tmp,e[i^1].w+=tmp,used+=tmp; if (used==flow) break; } return used; } inline int CostFlow() { int Flow=0; while (spfa(S,T)) { vis[T]=1; while (vis[T]) { memset(vis,0,sizeof(vis)); Flow+=dfs(S,INF); } } return Flow; } void init() { ans=0; memset(head,0,sizeof(head)); Case++; S=0,T=n+1; } int main() { while (scanf("%d%d",&n,&m)!=EOF) { if (n==0 && m==0) break; init(); printf("Instance #%d: ",Case); for (int i=1,u,v,w ;i<=m;i++) { scanf("%d%d%d",&u,&v,&w); add(u+1,v+1,1,w); } add(S,1,2,0); add(n,T,2,0); if (CostFlow()==2) printf("%d\n",ans); else puts("Not possible"); } return 0; }