您的位置:首页 > 其它

bzoj 1937: [Shoi2004]Mst 最小生成树

2016-06-21 19:18 260 查看
将原问题对偶成为费用流模型;

写的原始对偶的费用流,然后发现每次增广容量最多为1…mdzz

#include<bits/stdc++.h>
#define rep(i,k,n) for(int i=k;i<=(n);i++)
#define rep2(i,k,n) for(int i=k;i>=(n);i--)
#define mp make_pair
using namespace std;
const int N=1005;
const int M=100005;
const int inf=0x3f3f3f3f;
struct E{
int fr,to,next,cap,c;E(int fr=0,int to=0,int next=0,int cap=0,int c=0):fr(fr),to(to),next(next),cap(cap),c(c){}
}edge[M];
int head
,tot=1;
void Add(int x,int y,int cap,int cost){
edge[++tot]=E(x,y,head[x],cap,cost);head[x]=tot;
edge[++tot]=E(y,x,head[y],0,-cost);head[y]=tot;
}
int n,m,op
,V
,cnt=0,S,T;
map<pair<int,int>,int> st;
map<int,pair<int,int> > nst;
namespace tu{
struct E2{
int fr,to,next,num;E2(int fr=0,int to=0,int next=0,int num=0):fr(fr),to(to),next(next),num(num){}
}edge[M];
int head
,tot=0;
void add(int x,int y,int num){
edge[++tot]=E2(x,y,head[x],num);head[x]=tot;
edge[++tot]=E2(y,x,head[y],num);head[y]=tot;
}
int p
,ok;
void dfs(int u,int v,int fa){
if(u==v)ok=1;
if(ok)return;
for(int i=head[u];i;i=edge[i].next)if(op[edge[i].num]){
int to=edge[i].to;
if(to!=fa){
p[to]=i;
dfs(to,v,u);
}
}
}
void init(){int u,v;
rep(i,1,cnt)if(!op[i]){
memset(p,0,sizeof(p));ok=0;
u=nst[i].first,v=nst[i].second;
dfs(u,v,0);
int now=p[v];
while(now){
Add(edge[now].num,i,1,V[edge[now].num]-V[i]);
now=p[edge[now].fr];
}
}
}
}
int inq
,cur
,dis
;
queue<int> Q;
bool spfa(){
memset(inq,0,sizeof(inq));
memset(dis,-0x7f,sizeof(dis));
memcpy(cur,head,sizeof(head));
dis[T]=0;inq[T]=1;
Q.push(T);
while(!Q.empty()){
int u=Q.front();
Q.pop();inq[u]=0;
for(int i=head[u];i;i=edge[i].next)if(edge[i^1].cap){
int v=edge[i].to,w=edge[i].c;
if(dis[v]<dis[u]-w){
dis[v]=dis[u]-w;
if(!inq[v]){inq[v]=1;Q.push(v);}
}
}
}
return dis[S]>-inf;
}
int vis
;
int dfs(int u,int a){
vis[u]=1;
if(!a || u==T)return a;
int f,flow=0;
for(int& i=cur[u];i;i=edge[i].next)if(edge[i].cap){
int v=edge[i].to,cc=edge[i].cap;
if(dis[v]+edge[i].c==dis[u] && !vis[v]){
f=dfs(v,min(a,cc));
if(f){
edge[i].cap-=f;
edge[i^1].cap+=f;
flow+=f;
a-=f;
if(!a)return flow;
}
}
}
return flow;
}
int main(){
//  freopen("in.in","r",stdin);
//  freopen("out.out","w",stdout);
scanf("%d%d",&n,&m);int x,y,w;
rep(i,1,m){
scanf("%d%d",&x,&y);if(x>y)swap(x,y);
st[mp(x,y)]=++cnt;
nst[cnt]=mp(x,y);
scanf("%d",&w);
V[cnt]=w;
tu::add(x,y,cnt);
}rep(i,1,n-1){
scanf("%d%d",&x,&y);if(x>y)swap(x,y);
op[st[mp(x,y)]]=1;
}tu::init();
S=++cnt,T=++cnt;
rep(i,1,cnt-2)
if(op[i])Add(S,i,1,0);
else Add(i,T,1,0);
int ans=0;
while(spfa()){
if(dis[S]<=0)break;
memset(vis,0,sizeof(vis));
ans+=dis[S]*dfs(S,inf);
}printf("%d\n",ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  线性规划