Input The first line contains one integer T (1<=T<=20), the number of test cases.
Then T test cases follow. The first line of each test case contains two integers N and M (2<=N,M<=100000), the number of islands and the number of routes. Islands are number from 1 to N.
Then N lines follow. Each line contain two integers, the X and Y coordinate of an island. The K-th line in the N lines describes the island K. The absolute values of all the coordinates are no more than 100000.
Then M lines follow. Each line contains three integers I1, I2 (1<=I1,I2<=N) and C (1<=C<=10000) . It means there is a route connecting island I1 and island I2, and it can transport C passengers in one direction within an hour.
It is guaranteed that the routes obey the rules described above. There is only one island is westernmost and only one island is easternmost. No two islands would have the same coordinates. Each island can go to any other island by the routes.
Output
For each test case, output an integer in one line, the transport capacity.
Sample Input
2
5 7
3 3
3 0
3 1
0 0
4 5
1 3 3
2 3 4
2 4 3
1 5 6
4 5 3
1 4 4
3 4 2
6 7
-1 -1
0 1
0 2
1 0
1 1
2 3
1 2 1
2 3 6
4 5 5
5 6 3
1 4 6
2 5 5
3 6 4
Sample Output
9 6
题解:
题目大意:
就是有些岛,岛与岛之间有路,给你岛的坐标,保证最东边和最西边的岛只有一个,问你从最西边走到最东边的每一个小时可以走过的最多的人。
这个题目,很明显是网络流,原因呢,就是因为题目说每一个小时内可以走的最多的人,但是又没有告诉你速度,再画一下图,发现其实就是一次性可以走多少人。
就是一个最大流的裸题,但是这里有一点不同就是这个建图,这个是一个双向的,是一个有环无向图,所以呢,这个建图就是正着和反着的容量应该是一样的。
这个具体为什么我还要去研究一下,现在就线这么认为吧。
然后就跑一个最大流的模板就可以了。
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <iostream>
#include <queue>
#include <vector>
#include <map>
#include <cstring>
#include <string>
#define inf 0x3f3f3f3f
using namespace std;
const int maxn = 1e5 + 5;
const int INF = 0x3f3f3f3f;
struct edge
{
int u, v, c, f;
edge(int u, int v, int c, int f) :u(u), v(v), c(c), f(f) {}
};
vector<edge>e;
vector<int>G[maxn];
int level[maxn];//BFS分层,表示每个点的层数
int iter[maxn];//当前弧优化
int m, s, t;
void init(int n)
{
for (int i = 0; i <= n; i++)G[i].clear();
e.clear();
}
void add(int u, int v, int c)
{
e.push_back(edge(u, v, c, 0));
e.push_back(edge(v, u, c, 0));
m = e.size();
G[u].push_back(m - 2);
G[v].push_back(m - 1);
}
void BFS(int s)//预处理出level数组
//直接BFS到每个点
{
memset(level, -1, sizeof(level));
queue<int>q;
level[s] = 0;
q.push(s);
while (!q.empty())
{
int u = q.front();
if (u == t) return;
q.pop();
for (int v = 0; v < G[u].size(); v++)
{
edge& now = e[G[u][v]];
if (now.c > now.f && level[now.v] < 0)
{
level[now.v] = level[u] + 1;
q.push(now.v);
}
}
}
}
int dfs(int u, int t, int f)//DFS寻找增广路
{
if (u == t)return f;//已经到达源点,返回流量f
for (int &v = iter[u]; v < G[u].size(); v++)
//这里用iter数组表示每个点目前的弧,这是为了防止在一次寻找增广路的时候,对一些边多次遍历
//在每次找增广路的时候,数组要清空
{
edge &now = e[G[u][v]];
if (now.c - now.f > 0 && level[u] < level[now.v])
//now.c - now.f > 0表示这条路还未满
//level[u] < level[now.v]表示这条路是最短路,一定到达下一层,这就是Dinic算法的思想
{
int d = dfs(now.v, t, min(f, now.c - now.f));
if (d > 0)
{
now.f += d;//正向边流量加d
e[G[u][v] ^ 1].f -= d;
//反向边减d,此处在存储边的时候两条反向边可以通过^操作直接找到
return d;
}
}
}
return 0;
}
int Maxflow(int s, int t)
{
int flow = 0;
for (;;)
{
BFS(s);
if (level[t] < 0)return flow;//残余网络中到达不了t,增广路不存在
memset(iter, 0, sizeof(iter));//清空当前弧数组
int f;//记录增广路的可增加的流量
while ((f = dfs(s, t, INF)) > 0)
{
flow += f;
}
}
return flow;
}
int main()
{
int qw;
scanf("%d", &qw);
while(qw--)
{
int n, m;
scanf("%d%d", &n, &m);
init(n);
int mans = inf, mark = 0;
int mana = -inf, mark1 = 0;
for(int i=1;i<=n;i++)
{
int x, y;
scanf("%d%d", &x, &y);
if(x<mans)
{
mans = x;
s = i;
}
if(x>mana)
{
mana = x;
t = i;
}
}
for(int i=1;i<=m;i++)
{
int x, y, c;
scanf("%d%d%d", &x, &y, &c);
add(x, y, c);
}
int ans = Maxflow(s, t);
printf("%d\n", ans);
}
return 0;
}
原文:https://www.cnblogs.com/EchoZQN/p/10800417.html