题意:
给出一些点从最西边的点经过网络到最东边的点,问最大流量(无向图)
思路:
根据坐标找出最西边的点(源点)和最东边的点(汇点)。
建图也很直接,
无向图网络流,建边要正反向都要赋予流量值;如果有向图则正向流量值,反向为0。
卡时间。
Dinic用STL不行,都换成了数组。另外ISAP也行。
// 抛弃STL的Dinic , 7800ms
#pragma comment(linker,"/STACK:16777216")
#include <cstdio>
#include <cstring>
#include <algorithm>
const int INF = 0x3f3f3f3f;
const int maxn = 100000+50;
using namespace std;
int n, m;
// 图
struct Edge{
int v, cap, flow, next;
Edge(int b = 0, int c = 0, int d = 0):v(b),cap(c),flow(d){}
};
Edge edges[maxn*2];
int head[maxn], cnt;
int dis[maxn]; // 分层的编号
int cur[maxn];
void init(){
cnt = 0;
memset(head, -1, sizeof(head));
}
void addEdge(int u, int v, int cap){
edges[cnt].v = v; edges[cnt].cap = cap; edges[cnt].flow = 0;
edges[cnt].next = head[u]; head[u] = cnt++;
// 反向弧
edges[cnt].v = u; edges[cnt].cap = cap; edges[cnt].flow = 0;
edges[cnt].next = head[v]; head[v] = cnt++;
}
// 分层
int Q[maxn]; // 模拟队列
bool bfs(int s, int t){
memset(dis, -1, sizeof(dis));
dis[s] = 0;
int front = 0, rear = 0;
Q[rear++] = s;
while(front < rear){
int x = Q[front++];
if(x == t) return true;
for(int i = head[x]; i != -1; i = edges[i].next){
Edge& e = edges[i];
if(dis[e.v] == -1&&e.cap > e.flow){
dis[e.v] = dis[x] + 1;
Q[rear++] = e.v;
}
}
}
return dis[t] != -1;
}
int dfs(int s, int t, int cur_flow){
if(s == t||cur_flow == 0) return cur_flow;
int ans = 0;
//if(cur[s] == -1) cur[s] = head[s];
for(int& i = cur[s]; i != -1; i = edges[i].next){
int c = i;
Edge& e = edges[c];
if(dis[e.v] == dis[s] + 1&&e.cap > e.flow){
int a2 = min(cur_flow, e.cap-e.flow);
int w = dfs(e.v, t, a2);
edges[c].flow += w;
edges[c^1].flow -= w;
cur_flow -= w;
ans += w;
if(cur_flow <= 0) break;
}
}
return ans;
}
// 最大流
int Dinic(int s, int t){
int ans = 0;
while(bfs(s,t)){
memcpy(cur, head, (n+1)*4);
ans += dfs(s,t,INF);
}
return ans;
}
int main()
{
//freopen("in.txt","r",stdin);
int T; scanf("%d", &T);
while(T--){
init();
scanf("%d%d",&n,&m);
int sx = INF, tx = -INF;
int s,t;
for(int i = 1; i <= n; ++i){
int x,y; scanf("%d%d",&x,&y);
if(sx > x){ sx = x; s = i;}
if(tx < x){ tx = x; t = i;}
}
for(int i = 0; i < m; ++i){
int a,b,c; scanf("%d%d%d",&a,&b,&c);
addEdge(a,b,c);
}
printf("%d\n", Dinic(s,t));
}
fclose(stdin);
return 0;
}