题目链接
https://vjudge.net/problem/HDU-4280
题意
n个城市,m道路,道路有最大通行量,是双向通行的,求最西边城市到最东边城市最大通行量
思路
裸的最大流,坐标没必要存,记录一下源汇点就行了。
注意道路是双向的,所以建边要双向建边,本来增广路算法反向容量0的边就不用再建了。
附了两份代码,Dinic 7.6s,ISAP 3.2s。
代码
//Dinic
#include<cstdio>
#include<iostream>
#include<iomanip>
#include<map>
#include<string>
#include<queue>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define endl "\n"
//#define int long long
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int maxn=110010;
const int maxe=210010;
int head[maxn],cnt;
struct Edge{
int v;
int w;
int next;
}edge[maxe];
int n,n1,n2,m,k,s,t;
ll maxflow;
int deep[maxn];
int now[maxe];
void init(){
memset(head,-1,sizeof(head));
cnt=0;
maxflow=0;
return ;
}
void add(int u,int v,int w){
// cout<<u<<" "<<v<<" "<<w<<endl;
edge[cnt].v=v;
edge[cnt].w=w;
edge[cnt].next=head[u];
head[u]=cnt++;
}
inline bool bfs(){
memset(deep,0x3f,sizeof(deep));
queue<int>q;
q.push(s);deep[s] = 0;now[s] = head[s];
while(q.size()){
int x = q.front();q.pop();
for(int i=head[x];i!=-1;i=edge[i].next){
int y=edge[i].v;
if(edge[i].w>0&&deep[y]==inf){
q.push(y);
now[y]=head[y];
deep[y]=deep[x]+1;
if(y==t) return 1;
}
}
}
return 0;
}
ll dfs(int x,int flow){
if(x==t) return flow;
ll ans = 0,k,i;
for(i=now[x];i!=-1&&flow;i=edge[i].next){
now[x]=i;
int y=edge[i].v;
if(edge[i].w>0&&(deep[y]==deep[x]+1)){
k=dfs(y,min(flow,edge[i].w));
if(!k) deep[y]=inf;
edge[i].w-=k;
edge[i^1].w+=k;
ans+=k;
flow-=k;
}
}
return ans;
}
void dinic(){
while(bfs())
maxflow+=dfs(s,inf);
}
int main(){
IOS
int tn;
cin>>tn;
while(tn--){
init();
cin>>n>>m;
int mi=inf,ma=-inf;
for(int i=1;i<=n;i++){
int x,y;
cin>>x>>y;
if(x<mi){
mi=x;
s=i;
}
if(x>ma){
ma=x;
t=i;
}
}
while(m--){
int u,v,w;
cin>>u>>v>>w;
add(u,v,w);
add(v,u,w);
}
dinic();
cout<<maxflow<<endl;
}
return 0;
}
//ISAP
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#include<bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;
const int maxn=100050;
const int maxe=200050;
const int inf=0x3f3f3f3f;
struct Edge{
int v;
int w;
int next;
}edge[maxe];
int head[maxn],cnt;
int gap[maxn],last[maxn],dis[maxn];
int n,m;
void add(int u,int v,int w){
edge[cnt].next=head[u]; edge[cnt].v=v; edge[cnt].w=w; head[u]=cnt++;
}
void init(){
cnt=0;
memset(head,-1,sizeof(head));
}
void init_mf(int s,int t){
memset(gap,0,sizeof(gap));
memset(dis,0,sizeof(dis));
++gap[dis[t]=1];
for(int i=1;i<=n;i++) last[i]=head[i];
queue<int>q; q.push(t);
while(q.size()){
int x=q.front();q.pop();
for (int i=head[x];i!=-1;i=edge[i].next){
int v=edge[i].v;
if (!dis[v]) {
++gap[dis[v]=dis[x]+1];
q.push(v);
}
}
}
}
ll aug(int x,int s,int t,int mi){
if (x==t) return mi;
ll flow=0;
for (int &i=last[x];i!=-1;i=edge[i].next){
int v=edge[i].v;
if (dis[x]==dis[v]+1){
ll tmp=aug(v,s,t,min(mi,edge[i].w));
flow+=tmp,mi-=tmp,edge[i].w-=tmp,edge[i^1].w+=tmp;
if (!mi) return flow;
}
}
if (!(--gap[dis[x]])) dis[s]=n+1;
++gap[++dis[x]],last[x]=head[x];
return flow;
}
ll maxflow(int s,int t){
init_mf(s,t);
ll ret=aug(s,s,t,inf);
while (dis[s]<=n) ret+=aug(s,s,t,inf);
return ret;
}
int main() {
int tn;
scanf("%d",&tn);
while(tn--){
int s,t;
scanf("%d%d",&n,&m);
init();
int mi=inf,ma=-inf;
for(int i=1;i<=n;i++){
int x,y;
scanf("%d%d",&x,&y);
if(x<mi){
mi=x;
s=i;
}
if(x>ma){
ma=x;
t=i;
}
}
while(m--){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
add(v,u,w);
}
printf("%lld\n",maxflow(s,t));
}
return 0;
}