学会了网络流,就经常闲的没事儿刷网络流……于是乎来一发题解。

1. COGS2093 花园的守护之神

题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长。

用Dijkstra或者SPFA跑出来s-t最短路,然后把最短路DAG上的每条边的容量设为1,跑最小割即可。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #include<queue>
  5 #define INF ((~((1)<<(31)))>>(1))
  6 using namespace std;
  7 const int maxn=1010,maxe=500010;
  8 struct edge1{int from,to,prev;long long dis;}e1[maxe<<1];
  9 struct edge2{int to,cap,prev;}e2[maxe<<1];
 10 struct node{
 11     int x;
 12     long long dis;
 13     node(int x,long long dis):x(x),dis(dis){}
 14     bool operator<(const node &a)const{return dis>a.dis;}
 15 };
 16 void addedge1(int,int,long long);
 17 void addedge2(int,int,int);
 18 void Dijkstra(int,long long*);
 19 int Dinic();
 20 void bfs();
 21 int dfs(int,int);
 22 int n,m,s,t,last1[maxn]={0},len1=0,last2[maxn],len2=0,now[maxn],d[maxn],q[maxn],head,tail,x,y;
 23 long long dis[maxn],redis[maxn],z;
 24 bool vis[maxn];
 25 int main(){
 26 #define MINE
 27 #ifdef MINE
 28     freopen("greendam2002.in","r",stdin);
 29     freopen("greendam2002.out","w",stdout);
 30 #endif
 31     memset(last2,-1,sizeof(last2));
 32     scanf("%d%d%d%d",&n,&m,&s,&t);
 33     for(int i=1;i<=m;i++){
 34         scanf("%d%d%lld",&x,&y,&z);
 35         addedge1(x,y,z);
 36         addedge1(y,x,z);
 37     }
 38     Dijkstra(s,dis);
 39     Dijkstra(t,redis);
 40     for(int i=1;i<=(m<<1);i++)if(dis[e1[i].from]+e1[i].dis+redis[e1[i].to]==dis[t]){
 41         addedge2(e1[i].from,e1[i].to,1);
 42         addedge2(e1[i].to,e1[i].from,0);
 43     }
 44     printf("%d",Dinic());
 45 #ifndef MINE
 46     printf("\n--------------------DONE--------------------\n");
 47     for(;;);
 48 #endif
 49     return 0;
 50 }
 51 void addedge1(int x,int y,long long z){
 52     e1[++len1].from=x;
 53     e1[len1].to=y;
 54     e1[len1].dis=z;
 55     e1[len1].prev=last1[x];
 56     last1[x]=len1;
 57 }
 58 void addedge2(int x,int y,int z){
 59     e2[len2].to=y;
 60     e2[len2].cap=z;
 61     e2[len2].prev=last2[x];
 62     last2[x]=len2++;
 63 }
 64 void Dijkstra(int x,long long *dis){
 65     memset(vis,0,sizeof(vis));
 66     priority_queue<node>q;
 67     memset(dis,63,sizeof(long long)*maxn);
 68     dis[x]=0;
 69     q.push(node(x,0));
 70     while(!q.empty()){
 71         x=q.top().x;
 72         q.pop();
 73         if(vis[x])continue;
 74         vis[x]=true;
 75         for(int i=last1[x];i;i=e1[i].prev)if(dis[e1[i].to]>dis[x]+e1[i].dis){
 76             dis[e1[i].to]=dis[x]+e1[i].dis;
 77             q.push(node(e1[i].to,dis[e1[i].to]));
 78         }
 79     }
 80 }
 81 int Dinic(){
 82     int ans=0;
 83     for(;;){
 84         bfs();
 85         if(d[t]==INF)break;
 86         memset(now,0,sizeof(now));
 87         ans+=dfs(s,INF);
 88     }
 89     return ans;
 90 }
 91 void bfs(){
 92     int x;
 93     fill_n(d+1,n,INF);
 94     d[s]=0;
 95     head=tail=0;
 96     q[tail++]=s;
 97     while(head!=tail){
 98         x=q[head++];
 99         for(int i=last2[x];i!=-1;i=e2[i].prev)if(e2[i].cap>0&&d[e2[i].to]==INF){
100             d[e2[i].to]=d[x]+1;
101             q[tail++]=e2[i].to;
102         }
103     }
104 }
105 int dfs(int x,int delta){
106     if(x==t||!delta)return delta;
107     int flow=0,f;
108     for(int i=(now[x]?e2[now[x]].prev:last2[x]);i!=-1;i=e2[i].prev)if(e2[i].cap>0&&d[e2[i].to]==d[x]+1){
109         now[x]=i;
110         f=dfs(e2[i].to,min(delta,e2[i].cap));
111         if(!f)continue;
112         e2[i].cap-=f;
113         e2[i^1].cap+=f;
114         flow+=f;
115         delta-=f;
116         if(!delta)break;
117     }
118     return flow;
119 }
View Code

相关文章:

  • 2021-06-10
  • 2021-10-17
  • 2022-12-23
  • 2022-01-31
  • 2022-12-23
  • 2022-01-09
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2022-12-23
  • 2021-07-22
  • 2021-06-28
  • 2022-12-23
  • 2021-08-17
  • 2021-08-06
  • 2022-12-23
相关资源
相似解决方案