这题有2问
第一问SPFA
第二问先从1->n 求一遍最短路,再从n->1求一遍最短路,然后判定每条边是否可能在最短路上
即D[e[i].a]+Di[e[i].b]+e[i].t==ans
注意每条边的反向边也需要判断一下
然后跑一遍最大流就行了(最小割=最大流)
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
int h[505],n,m,en,en1,D[505],Di[505],flag[505],S,T,cur[505];
struct Es{
int a,b,t,c;
}E[200005];
struct Edge1{
int b,v,next;
}e1[300005];
struct Edge{
int b,f,next,back;
}e[300005];
void AddEdge1(int sa,int sb,int sc){
e1[++en1].b=sb;
e1[en1].v=sc;
e1[en1].next=h[sa];
h[sa]=en1;
}
void AddEdge(int sa,int sb,int sc){
e[++en].b=sb;
e[en].f=sc;
e[en].next=h[sa];
e[en].back=en+1;
h[sa]=en;
swap(sa,sb);
e[++en].b=sb;
e[en].f=0;
e[en].next=h[sa];
e[en].back=en-1;
h[sa]=en;
}
int Spfa(int S,int T){
queue<int> Q;
memset(D,127,sizeof(D));
memset(flag,0,sizeof(flag));
Q.push(S);
D[S]=0;
flag[S]=1;
while(!Q.empty()){
int u=Q.front();
Q.pop();
flag[u]=0;
for(int i=h[u];i;i=e1[i].next){
int v=e1[i].b;
if(D[u]+e1[i].v<D[v]){
D[v]=D[u]+e1[i].v;
if(!flag[v]){
Q.push(v);
flag[v]=1;
}
}
}
}
return D[T];
}
int Spfa2(int S,int T){
queue<int> Q;
memset(Di,127,sizeof(Di));
memset(flag,0,sizeof(flag));
Q.push(S);
Di[S]=0;
flag[S]=1;
while(!Q.empty()){
int u=Q.front();
Q.pop();
flag[u]=0;
for(int i=h[u];i;i=e1[i].next){
int v=e1[i].b;
if(Di[u]+e1[i].v<Di[v]){
Di[v]=Di[u]+e1[i].v;
if(!flag[v]){
Q.push(v);
flag[v]=1;
}
}
}
}
return Di[T];
}
int Bfs(){
queue<int> Q;
Q.push(S);
memset(flag,0,sizeof(flag));
flag[S]=1;
while(!Q.empty()){
int u=Q.front();
Q.pop();
for(int i=h[u];i;i=e[i].next){
int v=e[i].b;
if(flag[v] || !e[i].f)continue;
flag[v]=flag[u]+1;
Q.push(v);
}
}
return flag[T];
}
int Dfs(int u,int flow){
if(u==T)return flow;
int f=flow;
for(int &i=cur[u];i;i=e[i].next){
int v=e[i].b,fl;
if(flag[v]==flag[u]+1 && e[i].f && (fl=Dfs(v,min(f,e[i].f)))){
f-=fl;
e[i].f-=fl;
e[e[i].back].f+=fl;
if(f==0)return flow;
}
}
return flow-f;
}
int Dinic(){
int ans=0;
while(Bfs()){
for(int i=1;i<=n;i++)cur[i]=h[i];
ans+=Dfs(S,2100000000);
}
return ans;
}
int main(){
freopen("1266.in","r",stdin);
freopen("1266.out","w",stdout);
scanf("%d %d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d %d %d %d",&E[i].a,&E[i].b,&E[i].t,&E[i].c);
AddEdge1(E[i].a,E[i].b,E[i].t);
AddEdge1(E[i].b,E[i].a,E[i].t);
}
int ans1=Spfa(1,n),ans2=Spfa2(n,1);
memset(h,0,sizeof(h));
printf("%d\n",ans1);
for(int i=1;i<=m;i++){
if(D[E[i].a]+Di[E[i].b]+E[i].t==ans1){AddEdge(E[i].a,E[i].b,E[i].c);}
if(Di[E[i].a]+D[E[i].b]+E[i].t==ans1){AddEdge(E[i].b,E[i].a,E[i].c);}
}
S=1;T=n;
ans2=Dinic();
printf("%d\n",ans2);
return 0;
}
评论 (0)