Problem Description
输入n, m分别代表有n个城市,m条边,输入s,e代表起点,目的点。接下来n行输入w, i行代表城市i的放置检测器所需的价值。接下来m行,输入u,v代表城市u,v之间有边相连接。有*要从s-e问你至少需要多少价值来放检测器。
思路:
建图,然后跑dinic就可以了,核心就是建图。拆点,建边流量为点权。超级源点和起点建边,流量为无穷。目的点和超级汇点建边,流量为无穷。城市与城市之间建边,流量为无穷。核心是城市与城市建边,如何使得到一个城市先经过限流边,在到下一个城市。
#include<bits/stdc++.h>
using namespace std;
struct node
{
int to, cap, next;
};
#define inf 0x3f3f3f3f
node Map[100000];
int head[999], vis[999], cnt;
void add(int u, int v, int w)//前向星存图
{
Map[cnt].to = v;
Map[cnt].cap = w;
Map[cnt].next = head[u];
head[u] = cnt++;
Map[cnt].to = u;
Map[cnt].cap = 0;
Map[cnt].next = head[v];
head[v] = cnt++;
}
bool bfs(int s, int e)
{
memset(vis, -1, sizeof(vis));
queue<int> q;
q.push(s);
vis[s] = 0;
while(!q.empty())
{
s = q.front(), q.pop();
for(int i = head[s]; ~i; i = Map[i].next)
{
int to = Map[i].to, cap = Map[i].cap;
if(vis[to] == -1 && cap)
{
vis[to] = vis[s] + 1;
q.push(to);
}
}
}
if(vis[e] == -1) return 0;
else return 1;
}
int dfs(int s, int e, int f)
{
if(s == e) return f;
int ans = 0;
for(int i = head[s]; ~i; i = Map[i].next)
{
int to = Map[i].to, &cap = Map[i].cap;
if(vis[to] > vis[s] && cap)
{
int d = dfs(to, e, min(f, cap));
if(d)
{
cap -= d;
Map[i^1].cap += d;
f -= d;
ans += d;
if(!f) break;
}
}
}
if(ans) return ans;
vis[s] = -1;
return 0;
}
int dinic(int s, int e)
{
int ans = 0;
while(bfs(s, e))
{
ans += dfs(s, e, inf);
}
return ans;
}
int main()
{
int n, m, s, e, w, i, u, v;
while(~scanf("%d %d", &n, &m))
{
cnt = 0;
memset(head, -1, sizeof(head));
scanf("%d %d", &s, &e);
add(0, s, inf);
add(e+n, 2*n+1, inf);
for(i = 1; i <= n; i++)
{
scanf("%d", &w);
add(i, i + n, w);
}
while(m--)
{
scanf("%d %d", &u, &v);//这样建边可以保证,经过点肯定会经过限流的边
add(u+n, v, inf);
add(v+n, u, inf);
}
printf("%d\n", dinic(0, 2*n+1));//求最大流,就是最小割
}
}