题意:无向图有N(N <= 1000)个节点,M(M <= 10000)条边;从节点1走到节点N再从N走回来,图中不能走同一条边,且图中可能出现重边,问最短距离之和为多少?
思路:很经典的构图(看题解的);每条原图中的边赋予cap为1,表示只走一次。超级源点s和汇点t分别和起点终点连边,cap为2,这里cap为2就直接限制了只能有两次最大流;同时最大流中以权值限制得到的就是最小费用;很注意的一点就是此题为无向图带权值,建图时每条有向边建成两条即总边数为4*M。由于spfa找最短路是有方向的,所以这样并不会出现一条边找两次的可能;
#include<iostream> #include<cstdio> #include<cstring> #include<string.h> #include<algorithm> #include<vector> #include<cmath> #include<stdlib.h> #include<time.h> #include<stack> #include<set> #include<map> #include<queue> using namespace std; #define rep0(i,l,r) for(int i = (l);i < (r);i++) #define rep1(i,l,r) for(int i = (l);i <= (r);i++) #define rep_0(i,r,l) for(int i = (r);i > (l);i--) #define rep_1(i,r,l) for(int i = (r);i >= (l);i--) #define MS0(a) memset(a,0,sizeof(a)) #define MS1(a) memset(a,-1,sizeof(a)) #define MSi(a) memset(a,0x3f,sizeof(a)) #define inf 0x3f3f3f3f #define lson l, m, rt << 1 #define rson m+1, r, rt << 1|1 typedef long long ll; #define A first #define B second #define MK make_pair typedef __int64 ll; template<typename T> void read1(T &m) { T 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();} m = x*f; } template<typename T> void read2(T &a,T &b){read1(a);read1(b);} template<typename T> void read3(T &a,T &b,T &c){read1(a);read1(b);read1(c);} template<typename T> void out(T a) { if(a>9) out(a/10); putchar(a%10+'0'); } int T,kase = 1,i,j,k,n,m,s,t; const int M = 10007; int head[M],tot; struct Edge{ int from,to,cap,flow,Next,w; Edge(){} Edge(int f,int to,int cap,int Next,int w):from(f),to(to),cap(cap),Next(Next),w(w),flow(0){} }e[M<<2]; inline void ins(int u,int v,int w,int cap) { e[++tot] = Edge{u,v,cap,head[u],w}; head[u] = tot; } int d[2007],pre[2007],inq[2007],a[2007]; bool spfa() { MSi(d);MS0(inq); d[s] = 0; queue<int> q; q.push(s); inq[s] = 1;pre[s] = 0;a[s] = inf; while(!q.empty()){ int u = q.front();q.pop(); inq[u] = 0; for(int id = head[u];id; id = e[id].Next){ int v = e[id].to; if(d[v] > d[u] + e[id].w && e[id].cap > e[id].flow){ d[v] = d[u] + e[id].w; pre[v] = id; a[v] = min(a[u],e[id].cap - e[id].flow); if(!inq[v]){ q.push(v); inq[v] = 1;} } } } return d[t] != inf; } void solve() { ll ans = 0; while(spfa()){ ans += d[t]*a[t]; for(int u = t;u != s;u = e[pre[u]].from){ e[pre[u]].flow += a[t]; e[pre[u]^1].flow -= a[t]; } } printf("%I64d ",ans); } int main() { while(scanf("%d%d",&n,&m) == 2){ MS0(head);tot = 1; s = 0,t = n+1; int u,v,w; rep0(i,0,m){ read3(u,v,w); ins(u,v,w,1);ins(v,u,-w,0);// ** 下面不能省略,因为是无向输入的. ins(v,u,w,1);ins(u,v,-w,0); } ins(s,1,0,2);ins(1,s,0,0); ins(n,t,0,2);ins(t,n,0,0); solve(); } return 0; }