标签:
要做这题,先要明白图的割,说白了就是 为了让原点无法到汇点要删几条边(之所以叫割,就是在图面上切一刀,减掉最小的边是原点和汇点成为两个集合),想到了割先放着一会用。
题中说只有沿最短路走才有可能追上,那么就意味着图中的最短路可能不止一条,沿着最短路走才能追上,那么其他的走法就没用了,所以只要求原点到汇点的最短路径图的最小割就可以知道最少断几条边可以堵住人了,再说第二问,既然最短路不止一条,那么只要边数量最小的一条最短路不被堵上,那个人就能追上炸弹张了,其他的边都可以赌上一点问题没有,这样就是总点数-最小最短路边数 等于第二问
写完交了几便都不对,逼的没招了去和题解,结果发现建图建错了!真是二逼的可以、、、、、、、、、、
for(int i=1;i<=n;i++) { for(int j=0;j<g[i].size();j++) { edge e = g[i][j]; if(dis[e.to]-dis[i]==gg[i][e.to]) addedge(i,e.to,1); }
开始我是这么写的,后来我是这么写的
for(int u = 1; u <= n; u++) { for(int i = 0; i < g[u].size(); i++) { int v = g[u][i].to, w = g[u][i].cap; if(dis[u] + w == dis[v]) { addedge(u, v, 1); } } }
啥区别呢? 错的那个用了矩阵去访问边,但是点数和边数差那么多肯定是有重边的! 矩阵不能存重边!
AC代码,看见有人216ms ac 我就四百多、、、
#include<cstdio> #include<cstring> #include<iostream> #include<vector> #include<queue> #include<utility> #define maxn 2001 #define inf 0xfffffff using namespace std; typedef pair<int,int> P; struct edge { int to,cap,rev; }; vector<edge> group[maxn]; vector<edge> g[maxn]; int level[maxn],iter[maxn]; int dis[maxn],n,m,fro[maxn]; int vis[maxn],ans2; int gg[maxn][maxn]; void dijkstra() { for(int i=1;i<=n;i++) { dis[i]=inf; } dis[1]=0; priority_queue<P,vector<P>, greater<P> > que; que.push(P(0,1)); while(!que.empty()) { P p=que.top(); que.pop(); int v=p.second; if(dis[v]<p.first) continue; for(int i=0;i<g[v].size();i++) { edge e=g[v][i]; if(dis[e.to]>=dis[v]+e.cap) { dis[e.to]=dis[v]+e.cap; que.push(P(dis[e.to],e.to)); } } } } void addedge(int from,int to,int cap) { group[from].push_back((edge){to,cap,group[to].size()}); group[to].push_back((edge){from,0,group[from].size()-1}); } void build() { for(int u = 1; u <= n; u++) { for(int i = 0; i < g[u].size(); i++) { int v = g[u][i].to, w = g[u][i].cap; if(dis[u] + w == dis[v]) { addedge(u, v, 1); } } } /* for(int i=1;i<=n;i++) { for(int j=0;j<g[i].size();j++) { edge e = g[i][j]; if(dis[e.to]-dis[i]==gg[i][e.to]) addedge(i,e.to,1); } }*/ } void bfs(int s) { memset(level,-1,sizeof(level)); queue<int> que; level[s] = 0; que.push(s); while(!que.empty()) { int v=que.front(); que.pop(); for(int i=0;i<group[v].size();i++) { edge &e=group[v][i]; if(e.cap>0&&level[e.to]<0) { level[e.to]=level[v]+1; que.push(e.to); } } } } int dfs(int v,int t,int f) { if(v == t) return f; for(int &i=iter[v];i<group[v].size();i++) { edge &e=group[v][i]; if(e.cap>0&&level[v]<level[e.to]) { int d=dfs(e.to,t,min(f,e.cap)); if(d>0) { e.cap -= d; group[e.to][e.rev].cap +=d; return d; } } } return 0; } int max_flow(int s,int t) { int flow=0; while(true) { bfs(s); if(level[t]<0) return flow; memset(iter,0,sizeof(iter)); int f; while((f=dfs(s,t,inf))>0) { flow+=f; } } } int minedge() { for(int k=1;k<=n;k++) fro[k]=inf; fro[1]=0; queue<int> Q; Q.push(1); while(!Q.empty()) { int s=Q.front(); Q.pop(); if(s==n) break; for(int i=0;i<g[s].size();i++) { edge e=g[s][i]; if(dis[s]+e.cap==dis[e.to]) { if(fro[s]+1<fro[e.to]) { fro[e.to]=fro[s]+1; Q.push(e.to); } } } } return fro[n]; } int main() { // freopen("1007.in", "r", stdin); while(scanf("%d%d",&n,&m)!=EOF) { for(int i=1;i<=n;i++) g[i].clear(); memset(gg,0,sizeof(gg)); for(int i=0;i<m;i++) { int a,b,c; scanf("%d%d%d",&a,&b,&c); g[a].push_back((edge){b,c,0}); g[b].push_back((edge){a,c,0}); gg[a][b]=c; gg[b][a]=c; } for(int i=1;i<=maxn;i++) group[i].clear(); dijkstra(); ans2=minedge(); build(); int ans1 = max_flow(1,n); printf("%d %d\n",ans1,m-ans2); } return 0; }
标签:
原文地址:http://www.cnblogs.com/liboyan/p/4668940.html