标签:
总算今天静下心来学算法。。
Description
Input
Output
Sample Input
Sample Output
for(int i=1;i<=n;i++){ for(int j=0;j<g[i].size();j++){ int tmp=d[i]-d[g[i][j]]; if(tmp<0) tmp=-tmp; if(tmp==e[i][j]) addEdge(i,g[i][j],e[i][j]); } }
举个例子:i 结点在最短路中前于 j 结点,e[i][j] 表示从 j 到 i 到有向边权值,则 d[i]-d[j]<0,则判了 d[j]-d[i]==e[i][j],错误。这在某些情况下回使得新建的图多了一条边。
for(int i=1;i<=n;i++){ for(int j=0;j<g[i].size();j++){ if(d[i]+e[i][j]==d[j]) addEdge(i,g[i][j],e[i][j]); } }
最小割的定义和求法:
定义:设点集S,T,称将起点在 S 中,终点在 T 中 的所有边删除后将使得 s 无法到达 t 的的集合划分(S,T)称为一个 s-t 割。(s 在 S 中 t 在 T 中)
在求得最大流后,寻找增广路过程中标记的点为集合 S,其余点为 T ,即得最小割。
最小割中的边数即为第一问的答案。(详情见代码)
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<vector> #include<queue> using namespace std; #define maxn 2015 #define inf 0x3f3f3f3f struct Edge{ int from,to,cap,flow; Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f){} }; vector<Edge>E; vector<int>g[maxn],e[maxn],G[maxn]; int n,m,M,a,b,c,d[maxn],vis[maxn],num[maxn],bet[maxn],p[maxn]; void init(){ for(int i=0;i<=n;i++) g[i].clear(),e[i].clear(),G[i].clear(); E.clear(); memset(vis,0,sizeof(vis)); } void addEdge(int from,int to,int cap){ E.push_back(Edge(from,to,cap,0)); E.push_back(Edge(to,from,0,0)); M=E.size(); G[from].push_back(M-2); G[to].push_back(M-1); } void maxflow(int s,int t){ for(;;){ memset(bet,0,sizeof(bet)); queue<int>q; q.push(s); bet[s]=inf; while(!q.empty()){ int x=q.front();q.pop(); for(int i=0;i<G[x].size();i++){ Edge &ee=E[G[x][i]]; if(!bet[ee.to]&&ee.cap>ee.flow){ p[ee.to]=G[x][i]; bet[ee.to]=min(bet[x],ee.cap-ee.flow); q.push(ee.to); } } if(bet[t]) break; } if(!bet[t]) break; for(int u=t;u!=s;u=E[p[u]].from){ E[p[u]].flow+=bet[t]; E[p[u]^1].flow-=bet[t]; } } } void Dijk(){ memset(d,0x3f,sizeof(d)); memset(num,0x3f,sizeof(num)); d[1]=num[1]=0; for(int i=1;i<=n;i++){ int u=-1; for(int j=1;j<=n;j++) if(!vis[j]){ if(u==-1||d[j]<d[u]) u=j; } vis[u]=1; for(int j=0;j<g[u].size();j++) if(!vis[g[u][j]]){ int tmp=d[u]+e[u][j]; if(tmp==d[g[u][j]]) num[g[u][j]]=min(num[u]+1,num[g[u][j]]); if(tmp<d[g[u][j]]){ d[g[u][j]]=tmp; num[g[u][j]]=num[u]+1; } } } } int main(){ //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); //freopen("test.txt","r",stdin); while(~scanf("%d%d",&n,&m)){ init(); for(int i=0;i<m;i++){ scanf("%d%d%d",&a,&b,&c); g[a].push_back(b),e[a].push_back(c); g[b].push_back(a),e[b].push_back(c); } Dijk(); int ans1=0,ans2=m-num[n]; for(int i=1;i<=n;i++){ for(int j=0;j<g[i].size();j++){ if(e[i][j]+d[i]==d[g[i][j]]) addEdge(i,g[i][j],e[i][j]); } } maxflow(1,n); for(int i=0;i<E.size();i++){ Edge &ee=E[i]; if(bet[ee.from]&&!bet[ee.to]&&ee.cap>0) ans1++; } printf("%d %d\n",ans1,ans2); } return 0; }
以及Dinic:
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<vector> #include<queue> using namespace std; #define maxn 2015 #define inf 0x3f3f3f3f struct Edge{ int from,to,cap,flow; Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f){} }; vector<Edge>E; vector<int>g[maxn],e[maxn],G[maxn]; int n,m,M,a,b,c,d[maxn],vis[maxn],num[maxn],cur[maxn],dis[maxn]; void init(){ for(int i=0;i<=n;i++) g[i].clear(),e[i].clear(),G[i].clear(); E.clear(); memset(vis,0,sizeof(vis)); } void addEdge(int from,int to,int cap){ E.push_back(Edge(from,to,cap,0)); E.push_back(Edge(to,from,0,0)); M=E.size(); G[from].push_back(M-2); G[to].push_back(M-1); } bool bfs(){ memset(vis,0,sizeof(vis)); queue<int>q; q.push(1); dis[1]=0; vis[1]=1; while(!q.empty()){ int x=q.front();q.pop(); for(int i=0;i<G[x].size();i++){ Edge &ee=E[G[x][i]]; if(!vis[ee.to]&&ee.cap>ee.flow){ vis[ee.to]=1; dis[ee.to]=dis[x]+1; q.push(ee.to); } } } return vis[n]; } int dfs(int x,int a){ if(x==n||a==0) return a; int flow=0,f; for(int &i=cur[x];i<G[x].size();i++){ Edge &ee=E[G[x][i]]; if(dis[x]+1==dis[ee.to]&& (f=dfs(ee.to,min(a,ee.cap-ee.flow)))>0){ ee.flow+=f; E[G[x][i]^1].flow-=f; flow+=f; a-=f; if(a==0) break; } } return flow; } void maxflow(){ while(bfs()){ memset(cur,0,sizeof(cur)); dfs(1,inf); } } void Dijk(){ memset(d,0x3f,sizeof(d)); memset(num,0x3f,sizeof(num)); d[1]=num[1]=0; for(int i=1;i<=n;i++){ int u=-1; for(int j=1;j<=n;j++) if(!vis[j]){ if(u==-1||d[j]<d[u]) u=j; } vis[u]=1; for(int j=0;j<g[u].size();j++) if(!vis[g[u][j]]){ int tmp=d[u]+e[u][j]; if(tmp==d[g[u][j]]) num[g[u][j]]=min(num[u]+1,num[g[u][j]]); if(tmp<d[g[u][j]]){ d[g[u][j]]=tmp; num[g[u][j]]=num[u]+1; } } } } int main(){ //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); //freopen("test.txt","r",stdin); while(~scanf("%d%d",&n,&m)){ init(); for(int i=0;i<m;i++){ scanf("%d%d%d",&a,&b,&c); g[a].push_back(b),e[a].push_back(c); g[b].push_back(a),e[b].push_back(c); } Dijk(); int ans1=0,ans2=m-num[n]; for(int i=1;i<=n;i++){ for(int j=0;j<g[i].size();j++){ if(d[i]+e[i][j]==d[g[i][j]]) addEdge(i,g[i][j],e[i][j]); } } maxflow(); for(int i=0;i<E.size();i++){ Edge &ee=E[i]; if(ee.from==ee.to) continue; if(vis[ee.from]&&!vis[ee.to]&&ee.cap>0) ans1++; } printf("%d %d\n",ans1,ans2); } return 0; }
标签:
原文地址:http://www.cnblogs.com/names-yc/p/4703024.html