bzoj1266: [AHOI2006]上学路线route
最短路+最小割
首先如何使最短路变长?就是要每一条最短路都割一条边。
我们求出每个点到点1和点n的距离,就可以知道哪些边在最短路上(一开始没有想到求到0和n的距离,想用floyd,但是n=500,怕超时。)
第二步呢,我们把每条在最短路上的边加入一个新图,跑最小割就可以了(把所有最短路都割掉一条边,最短路就变长了,这个也没想到)
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn = 500 + 10; const int maxm = 300000 + 10; const int inf = 0x3f3f3f3f; struct Edge { int u,v,t,c; }e[maxm]; int g[maxn],v[maxm],next[maxm],c[maxm],eid; int n,m,S,T,u,vid; int gap[maxn],dist[2][maxn],d[maxn]; int q[maxm*10],l,r; bool inque[maxn]; void addedge(int a,int b,int C) { v[eid]=b; c[eid]=C; next[eid]=g[a]; g[a]=eid++; } void build() { memset(g,-1,sizeof(g)); scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { scanf("%d%d%d%d",&e[i].u,&e[i].v,&e[i].t,&e[i].c); addedge(e[i].u,e[i].v,e[i].t); addedge(e[i].v,e[i].u,e[i].t); } } void spfa(int S,int dist[]) { l=r=0; q[r++]=S; memset(dist,0x3f,sizeof(dist)); dist[S]=0; while(l<r) { inque[u=q[l++]]=0; for(int i=g[u];~i;i=next[i]) if(dist[v[i]]>dist[u]+c[i]) { dist[v[i]]=dist[u]+c[i]; if(!inque[v[i]]) inque[q[r++]=v[i]]=1; } } } void predo() { memset(dist,0x3f,sizeof(dist)); spfa(1,dist[0]); spfa(n,dist[1]); printf("%d\n",dist[0][n]); S=1; T=n; memset(g,-1,sizeof(g)); eid=0; for(int i=1;i<=m;i++) { if(dist[0][e[i].u]+e[i].t+dist[1][e[i].v]==dist[0][n]) { addedge(e[i].u,e[i].v,e[i].c); addedge(e[i].v,e[i].u,0); } if(dist[0][e[i].v]+e[i].t+dist[1][e[i].u]==dist[0][n]) { addedge(e[i].v,e[i].u,e[i].c); addedge(e[i].u,e[i].v,0); } } } int ISAP(int u,int flow) { if(u==T) return flow; int cur=0,aug,mindist=vid; for(int i=g[u];~i;i=next[i]) if(c[i] && d[v[i]]+1==d[u]) { aug=ISAP(v[i],min(flow-cur,c[i])); c[i]-=aug; c[i^1]+=aug; cur+=aug; if(cur==flow || d[S]>=vid) return cur; } if(cur==0) { if(!--gap[d[u]]) { d[S]=vid; return cur; } for(int i=g[u];~i;i=next[i]) if(c[i]) mindist=min(mindist,d[v[i]]); ++gap[d[u]=mindist+1]; } return cur; } void solve() { int res=0; memset(d,0,sizeof(d)); vid=n; gap[0]=vid; while(d[S]<vid) res+=ISAP(S,inf); printf("%d\n",res); } int main() { build(); predo(); solve(); return 0; }