题目链接:点我~~
题意:1000个点10000条边的无向图,敌人从n走一条最短路到1,在第i条路设置障碍的代价是wi,求最少的代价使得敌人至少会遇到一次障碍。
思路:先确定最短路,然后在最短路径上跑一个网络流,即可求出最小割。
#include <bits/stdc++.h> using namespace std; typedef long long LL; typedef unsigned long long ULL; typedef pair<int, int> PI; typedef pair< PI, int> PII; const double eps=1e-5; const double pi=acos(-1.0); const int mod=1e9+7; const int INF=0x3f3f3f3f; #define lson l, m, rt<<1 #define rson m+1, r, rt<<1|1 const int MAXN = 1000+100; const int MAXM = 20100; struct node { int v; int cost; node(int _v=0,int _cost=0):v(_v),cost(_cost) {} }; vector<node>E[MAXN]; void add(int u,int v,int w) { E[u].push_back(node(v,w)); } bool vis[MAXN]; int cnt[MAXN]; int dist[MAXN]; bool SPFA(int start,int n) { memset(vis,false,sizeof(vis)); for(int i=1; i<=n; i++)dist[i]=INF; vis[start]=true; dist[start]=0; queue<int>que; while(!que.empty())que.pop(); que.push(start); memset(cnt,0,sizeof(cnt)); cnt[start]=1; while(!que.empty()) { int u=que.front(); que.pop(); vis[u]=false; for(int i=0; i<E[u].size(); i++) { int v=E[u][i].v; if(dist[v]>dist[u]+1) { dist[v]=dist[u]+1; if(!vis[v]) { vis[v]=true; que.push(v); } } } } return true; } struct Edge { int to,next,cap,flow; } edge[MAXM]; int tol; int head[MAXN]; int gap[MAXN],dep[MAXN],pre[MAXN],cur[MAXN]; void init() { tol = 0; memset(head,-1,sizeof(head)); } void addedge(int u,int v,int w,int rw=0) { edge[tol].to = v; edge[tol].cap = w; edge[tol].next = head[u]; edge[tol].flow = 0; head[u] = tol++; edge[tol].to = u; edge[tol].cap = rw; edge[tol].next = head[v]; edge[tol].flow = 0; head[v]=tol++; } int sap(int start,int end,int N) { memset(gap,0,sizeof(gap)); memset(dep,0,sizeof(dep)); memcpy(cur,head,sizeof(head)); int u = start; pre[u] = -1; gap[0] = N; int ans = 0; while(dep[start] < N) { if(u == end) { int Min = INF; for(int i = pre[u]; i != -1; i = pre[edge[i^1].to]) if(Min > edge[i].cap - edge[i].flow) Min = edge[i].cap - edge[i].flow; for(int i = pre[u]; i != -1; i = pre[edge[i^1].to]) { edge[i].flow += Min; edge[i^1].flow -= Min; } u = start; ans += Min; continue; } bool flag = false; int v; for(int i = cur[u]; i != -1; i = edge[i].next) { v = edge[i].to; if(edge[i].cap - edge[i].flow && dep[v]+1 == dep[u]) { flag = true; cur[u] = pre[v] = i; break; } } if(flag) { u = v; continue; } int Min = N; for(int i = head[u]; i != -1; i = edge[i].next) if(edge[i].cap - edge[i].flow && dep[edge[i].to] < Min) { Min = dep[edge[i].to]; cur[u] = i; } gap[dep[u]]--; if(!gap[dep[u]])return ans; dep[u] = Min+1; gap[dep[u]]++; if(u != start) u = edge[pre[u]^1].to; } return ans; } int main() { int t; scanf("%d",&t); while(t--) { int n,m; init(); for(int i=0; i<=n; ++i) E[i].clear(); scanf("%d%d",&n,&m); int u,v,w; for(int i=0; i<m; ++i) { scanf("%d%d%d",&u,&v,&w); add(u,v,w); add(v,u,w); } SPFA(1,n); for(int i=1; i<=n; ++i) { for(int j=0; j<E[i].size(); ++j) { if(dist[E[i][j].v]==dist[i]+1) addedge(i,E[i][j].v,E[i][j].cost); } } printf("%d\n",sap(1,n,n)); } return 0; }
- 版权声明:本文基于《知识共享署名-相同方式共享 3.0 中国大陆许可协议》发布,转载请遵循本协议
- 文章链接:http://www.carlstedt.cn/archives/1166 (转载时请注明本文出处及文章链接)
发表评论
快来吐槽一下吧!