您的位置:首页 > 其它

2016夏季练习——最小树形图

2016-07-27 21:30 295 查看
来源:HDU4966

终于见识到了传说中的建图问题,建图建的真是666啊。。。

代码:

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int INF = 0x3f3f3f3f;
const int MAXN = 555;
const int MAXE = 2555;
struct Edge{
int u,v;
int w;
}edge[MAXE];
int level[60][510];
int des[60];
int pre[MAXE],id[MAXE],vis[MAXE],in[MAXE];
int zhuliu(int root,int n,int m){
int ans = 0;
int v,u;
while(1){
for(int i=0;i<n;i++)
in[i] = INF;
for(int i=0;i<m;i++){
u = edge[i].u;
v = edge[i].v;
if(u!=v&&in[v]>edge[i].w){
pre[v]=u;
in[v]=edge[i].w;
}
}
for(int i=0;i<n;i++){
if(i!=root&&in[i]==INF)
return -1;
}

int tn = 0;
memset(id,-1,sizeof(id));
memset(vis,-1,sizeof(vis));
in[root] = 0;
for(int i=0;i<n;i++){
ans+=in[i];
v = i;
while(vis[v]!=i&&v!=root&&id[v]==-1){
vis[v] = i;
v = pre[v];
}
if(v!=root&&id[v]==-1){
for(u = pre[v];u!=v;u=pre[u]){
id[u] = tn;
}
id[v] = tn++;
}
}
if(tn==0) {
return ans;
}
for(int i=0;i<n;i++){
if(id[i]==-1) id[i]=tn++;
}
for(int i=0;i<m;i++){
v = edge[i].v;
edge[i].u = id[edge[i].u];
edge[i].v = id[edge[i].v];
if(edge[i].v!=edge[i].u)
edge[i].w -= in[v];
}
n = tn;
root = id[root];
}
return ans;
}
int main(){
int n,m;
int ID;
while(scanf("%d%d",&n,&m)!=EOF){
if(m==0&&n==0) break;
ID=1;
for(int i=1;i<=n;i++){
scanf("%d",&des[i]);
for(int j=0;j<=des[i];j++){
level[i][j]=ID++;
}
}
int c,L1,d,L2,w;
int cnt=0;
for(int i=0;i<m;i++){
scanf("%d%d%d%d%d",&c,&L1,&d,&L2,&w);
edge[cnt].u=level[c][L1];
edge[cnt].v=level[d][L2];
edge[cnt++].w=w;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=des[i];j++){
edge[cnt].v=level[i][j-1];
edge[cnt].u=level[i][j];
edge[cnt++].w=0;
}
}
for(int i=1;i<=n;i++){
edge[cnt].u = 0;
edge[cnt].v = level[i][0];
edge[cnt++].w = 0;
}
n = ID;//刚好加上0点
cout<<zhuliu(0,n,cnt)<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: