分析题意可知:
1、最少需要切断多少边使吴不能找到张(题意吴只能走最短路径上面的边),对从起点到终点的最短路径重新建图,每条边的权值为1,求最大流即可
2、在吴可以找到张的前提下,最多可以切断边的数量:只需要在所有最短路径中寻找一条经过边数量最少的最短路径,用边的总数减去它即可(逆向思维)
代码如下:
#include <cstdio> #include <cstring> #include <vector> #include <queue> #define MAXN 2010 #define INF 1e9+7 using namespace std; struct Edge { int v,cost,cap;///v代表边的另一个顶点,cost代表边的代价,cap代表反向边的位置 Edge(int _v=0,int _cost=0,int _cap=0):v(_v),cost(_cost),cap(_cap) {} }; vector<Edge> g[MAXN];///保存地图 vector<int> pre[MAXN];///记录最短路径上每个节点的父节点,用于构建网络流 int flag[MAXN][MAXN];///解决重边问题 int d[MAXN];///记录到达某一点的最短路径所经过的最短的边,用于求解问题2 int dist[MAXN]; struct qnode { int v; int c; qnode(int _v=0,int _c=0):v(_v),c(_c) {} bool operator<(const qnode &r)const { return c>r.c; } }; int n,m; int level[MAXN]; void Dijkstra(int s); void addedge(int u,int v,int w,int cap); void built(int u); int DINIC(int s,int t); int DFS(int now,int maxf,int t); bool makelevel(int s,int t); int main() { //FILE* fp = fopen("C:\\Users\\Crazy_Bear\\Desktop\\数据\\data1007\\1007.in","rw"); while(scanf("%d%d",&n,&m)==2) { memset(g,0,sizeof(g)); memset(flag,0,sizeof(flag)); int x,y,v; for(int i=1; i<=m; ++i) { //fscanf(fp,"%d%d%d",&x,&y,&v); scanf("%d%d%d",&x,&y,&v); flag[x][y]++;///记录重边的数量 addedge(x,y,v,0); flag[y][x]++; addedge(y,x,v,0); } Dijkstra(1); memset(g,0,sizeof(g)); built(n);///重新建图 printf("%d %d\n",DINIC(1,n),m-d[n]); } // fclose(fp); return 0; } void addedge(int u,int v,int w,int cap) { g[u].push_back(Edge(v,w,cap)); } void Dijkstra(int s) { bool vis[MAXN]; for(int i=1; i<=n; ++i) { vis[i]=false; dist[i]=INF; pre[i].clear(); d[i]=INF; } priority_queue<qnode> pq; while(!pq.empty()) pq.pop(); dist[s]=0; d[s]=0; pq.push(qnode(s,0)); qnode tmp; while(!pq.empty()) { tmp=pq.top(); pq.pop(); int u=tmp.v; if(vis[u]) continue; vis[u]=true; for(int i=0; i<g[u].size(); ++i) { int v=g[u][i].v; int cost=g[u][i].cost; if(dist[v]==dist[u]+cost) { pre[v].push_back(u);///在求解最短路径的过程中记录父节点 d[v]=min(d[u]+1,d[v]); } else if(dist[v]>dist[u]+cost) { dist[v]=dist[u]+cost; pq.push(qnode(v,dist[v])); d[v]=d[u]+1; pre[v].clear(); pre[v].push_back(u); } } } } void built(int u) { if(u==1) return; int len=pre[u].size(); for(int i=0; i<len; ++i) { if(flag[pre[u][i]][u]>0) { addedge(pre[u][i],u,1,g[u].size()); flag[pre[u][i]][u]--; addedge(u,pre[u][i],1,g[pre[u][i]].size()-1); flag[u][pre[u][i]]--; built(pre[u][i]); } } } bool makelevel(int s,int t) { memset(level,0,sizeof(level)); level[s]=1; int que[MAXN]; int iq=0; que[iq++]=s; int top; for(int i=0; i<iq; ++i) { top=que[i]; if(top==t) return true; int len=g[top].size(); for(int i=0; i<len; ++i) { if(!level[g[top][i].v]&&g[top][i].cost) { que[iq++]=g[top][i].v; level[g[top][i].v]=level[top]+1; } } } return false; } int DFS(int now,int maxf,int t) { if(now==t) return maxf; int ret=0,f; int len=g[now].size(); for(int i=0; i<len; ++i) { if(g[now][i].cost&&level[g[now][i].v]==level[now]+1) { f=DFS(g[now][i].v,min(maxf-ret,g[now][i].cost),t); g[now][i].cost-=f; g[g[now][i].v][g[now][i].cap].cost+=f; ret+=f; if(ret==maxf) return ret; } } return ret; } int DINIC(int s,int t) { int ans=0; while(makelevel(s,t)) ans+=DFS(s,INF,t); return ans; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-08 02:25:17