NOIP模拟赛花园的守护之神(greendam)-最短路-最大流最小割
Posted SkyLYnf
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NOIP模拟赛花园的守护之神(greendam)-最短路-最大流最小割相关的知识,希望对你有一定的参考价值。
Problem Greemdam
题目大意
给一个图$G=(V,E)$,求要使这个图的最短路增长所需要增加的最小权值的值。
Solution
既然是要求这个玩意儿,我们可以排除除了最短路以外的所有路径,因为这些是无用的。
对于每一条最短路路径,如果这条路径与任意一个最短路路径有相同的一条边,
那我们只需要在这条边权值加一就可以保证这两个最短路都增加了。
所以我们转化为求不相交边的最短路路径数,
其实就是这个图的最小割。
我们给最短路的图每个边附权值为1(因为前权值是无用的),
跑一遍最大流即可。
Dijkstra跑的要比spfa快。最好加个优先队列优化。
Datamaker
首先声明这个datamaker是无用的,最多只能让你看看极限数据跑多久。
因为随机出来数据所有的答案都是1。
1 #include <iostream> 2 #include <ctime> 3 #include <cstdio> 4 #define MAXN 1000 5 #define MAXM 500000 6 #define MAXC 1000000 7 using namespace std; 8 int main(){ 9 freopen("b.in","w",stdout); 10 srand(time(NULL)); 11 int st=rand()%(MAXN-1)+1,ed=rand()%(MAXN-1)+1; 12 while(st==ed)ed=rand()%(MAXN-1)+1; 13 printf("%d %d %d %d\n",MAXN,MAXM,st,ed); 14 for(int i=1;i<=MAXM;i++) 15 printf("%d %d %d\n",rand()%(MAXN-1)+1,rand()%(MAXN-1)+1,rand()%(MAXC-1)+1); 16 }
AC Code
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <queue> 6 #define INF 1e15 7 #define ll long long 8 using namespace std; 9 struct node{ 10 int to,next,from; 11 ll w; 12 }e[1000010]; 13 struct nodee{ 14 int to,next,w; 15 }a[1000010]; 16 typedef pair<int,int> pa; 17 int n,m,st,ed,u,v,ans=0,tot=0,tott=1; 18 int h[1010],hh[1010],dis[1010],q[1010]; 19 ll w,d[1010]; 20 bool visit[1010]; 21 void add(int u,int v,ll w){ 22 e[++tot].to=v;e[tot].next=h[u]; 23 h[u]=tot;e[tot].w=w;e[tot].from=u; 24 e[++tot].to=u;e[tot].next=h[v]; 25 h[v]=tot;e[tot].w=w;e[tot].from=v; 26 } 27 void insr(int u,int v,int w){ 28 a[++tott].to=v;a[tott].next=hh[u]; 29 hh[u]=tott;a[tott].w=w; 30 a[++tott].to=u;a[tott].next=hh[v]; 31 hh[v]=tott;a[tott].w=0; 32 } 33 bool bfs(){ 34 int head=0,tail=1; 35 memset(dis,-1,sizeof(dis)); 36 dis[st]=0;q[0]=st; 37 while(head!=tail){ 38 int now=q[head]; 39 for(int i=hh[now];~i;i=a[i].next) 40 if(a[i].w&&dis[a[i].to]==-1){ 41 dis[a[i].to]=dis[now]+1; 42 q[tail++]=a[i].to; 43 } 44 head++; 45 } 46 return dis[ed]!=-1; 47 } 48 int dfs(int now,int flow){ 49 if(now==ed)return flow; 50 int w,used=0; 51 for(int i=hh[now];~i;i=a[i].next) 52 if(dis[now]+1==dis[a[i].to]){ 53 w=dfs(a[i].to,min(a[i].w,flow-used)); 54 a[i].w-=w; 55 a[i^1].w+=w; 56 used+=w; 57 if(used==flow)return flow; 58 } 59 if(!used)dis[now]=-1; 60 return used; 61 } 62 void dijkstra(){ 63 memset(visit,0,sizeof(visit)); 64 for(int i=1;i<=n;i++)d[i]=INF; 65 d[st]=0; 66 priority_queue<pa,vector<pa>,greater<pa>> q; 67 q.push(make_pair(0,st)); 68 while(!q.empty()){ 69 int now=q.top().second; 70 q.pop(); 71 if(!visit[now]){ 72 visit[now]=1; 73 for(int i=h[now];~i;i=e[i].next) 74 if(d[now]+e[i].w<d[e[i].to]){ 75 d[e[i].to]=d[now]+e[i].w; 76 q.push(make_pair(d[e[i].to],e[i].to)); 77 } 78 } 79 } 80 } 81 int main(){ 82 //freopen("b.in","r",stdin); 83 //freopen("b.out","w",stdout); 84 memset(h,-1,sizeof(h)); 85 memset(hh,-1,sizeof(hh)); 86 scanf("%d%d%d%d",&n,&m,&st,&ed); 87 for(int i=1;i<=m;i++){ 88 scanf("%d%d%lld",&u,&v,&w); 89 add(u,v,w); 90 } 91 dijkstra(); 92 for(int i=1;i<=tot;i++) 93 if(d[e[i].from]+e[i].w==d[e[i].to]) 94 insr(e[i].from,e[i].to,1); 95 while(bfs()) 96 ans+=dfs(st,1e9); 97 printf("%d",ans); 98 }
以上是关于NOIP模拟赛花园的守护之神(greendam)-最短路-最大流最小割的主要内容,如果未能解决你的问题,请参考以下文章