最短路+最小割
/************************************************************** Problem: 1266 User: lxy8584099 Language: C++ Result: Accepted Time:2708 ms Memory:6744 kb ****************************************************************/ /* n=500 故意给这么小 就往floyd方向考虑 先求出最短路 如果对于一条路径有 d 1,i + d i,j +d j,n == d 1,n 可知 i->j一定是某一最短路上的边 于是吧所有这些边提取出来 求最小割即可! NOTE: 注意边的去重 */ #include<queue> #include<cstdio> #include<cstring> using namespace std; const int N=505,M=125000; struct road { int u,v,d,c; road(){} road(int _u,int _v,int _d,int _c) {u=_u,v=_v,d=_d,c=_c;} } r[M]; struct pp {int v,nxt,c;} e[M<<1]; int head[N],dep[N],n,m,tot=1,d[N][N],st,ed,tax[N],cur[N]; inline int min(int a,int b) {return a>b?b:a;} inline void add(int u,int v,int c) { e[++tot].nxt=head[u];head[u]=tot;e[tot].v=v;e[tot].c=c; } inline void bfs() { queue < int > q; q.push(ed); tax[dep[ed]=1]++; while(!q.empty()) { int u=q.front();q.pop(); for(int j=head[u];j;j=e[j].nxt) { int v=e[j].v;if(dep[v]) continue; tax[dep[v]=dep[u]+1]++; q.push(v); } } } inline int dfs(int u,int flow) { if(u==ed) return flow; int s=0,val; for(int&j=cur[u];j;j=e[j].nxt) { int v=e[j].v,c=e[j].c; if(dep[v]+1==dep[u]&&c>0) { s+=(val=dfs(v,min(c,flow-s))); e[j].c-=val;e[j^1].c+=val; if(s==flow) return s; } } --tax[dep[u]]; if(tax[dep[u]]==0) dep[st]=n+1; tax[++dep[u]]++; return s; } int main() { memset(d,0x3f,sizeof(d)); scanf("%d%d",&n,&m); st=1; ed=n; for(int i=1;i<=n;i++) d[i][i]=0; for(int i=1,u,v,t,c;i<=m;i++) { scanf("%d%d%d%d",&u,&v,&t,&c); r[i]=road(u,v,t,c); d[u][v]=d[v][u]=min(d[u][v],t); } for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) d[i][j]=min(d[i][j],d[i][k]+d[k][j]); for(int i=1;i<=m;i++) { int u=r[i].u,v=r[i].v,w=r[i].d,c=r[i].c; if(u==v) continue; if(d[1][u]+w+d[v][n]==d[1][n]) add(u,v,c),add(v,u,0); if(d[1][v]+w+d[u][n]==d[1][n]) add(v,u,c),add(u,v,0); } int res=0; bfs(); while(dep[st]<=n) { memcpy(cur,head,sizeof(head)); res+=dfs(st,23333333); } printf("%d\n%d\n",d[1][n],res); return 0; }