您的位置:首页 > 其它

UVa10600 ACM Contest and Blackout(最小和次小生成树)

2017-10-25 21:10 471 查看
简介:

最小生成树和次小生成树

分析:

当图变成了一棵树(纠结的生成树)

//这里写代码片
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>

using namespace std;

const int INF=0x33333333;
int maxline[103][103];
struct node1{
int x,y,v;
};
node1 e[20005];
struct node2{
int x,y,v,nxt;
};
node2 way[203];
int st[103],tot,fa[103],n,m;
bool p[103],pw[103];

bool operator < (const node1 &a,const node1 &b){return a.v<b.v;}

void add(int u,int w,int z)
{
tot++;
way[tot].x=u;way[tot].y=w;way[tot].v=z;way[tot].nxt=st[u];st[u]=tot;
tot++;
way[tot].x=w;way[tot].y=u;way[tot].v=z;way[tot].nxt=st[w];st[w]=tot;
}

int find(int x)
{
if (fa[x]!=x) fa[x]=find(fa[x]);
return fa[x];
}
void unionn(int f1,int f2){fa[f1]=f2;}

int Kruskal()
{
sort(e+1,e+1+m);
int cnt=0,ans=0;
for (int i=1;i<=n;i++) fa[i]=i;
for (int i=1;i<=m;i++)
{
int f1=find(e[i].x);
int f2=find(e[i].y);
if (f1!=f2)
{
cnt++; ans+=e[i].v;
unionn(f1,f2);
add(e[i].x,e[i].y,e[i].v);
pw[i]=0;
}
if (cnt==n-1) break;
}
return ans;
}

void dfs(int now,int f,int dis)                      //最小瓶颈路的最大边圈
{
if (f!=-1)
for (int j=1;j<=n;j++)                           //考虑所有已访问过的节点
if (!p[j])
maxline[now][j]=maxline[j][now]=max(maxline[j][f],dis);

p[now]=0;
for (int i=st[now];i;i=way[i].nxt)
if (way[i].y!=f&&p[way[i].y])
dfs(way[i].y,now,way[i].v);
}

int main()
{
int T;
scanf("%d",&T);
while (T--)
{
memset(st,0,sizeof(st));
memset(maxline,0,sizeof(maxline));
memset(p,1,sizeof(p));
memset(pw,1,sizeof(pw));                     //边是否在最小生成树中

scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++)
scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].v);

tot=0;
int ans1=Kruskal();
dfs(1,-1,0);
int ans2=INF;

for (int i=1;i<=m;i++)
if (pw[i])
ans2=min(ans2,ans1-maxline[e[i].x][e[i].y]+e[i].v);

printf("%d %d\n",ans1,ans2);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: