http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1541
题目大意:
大家新年快乐~
我们知道有最小生成树,这题是求比最小生成树大一点的,也就是求次小的生成树
思路:
新年第一战~1A~ 次小MST,半小时搞定~
和上一次那一次那一题一样。(点击直达:POJ 1679 The Unique 次最小生成树 MST)
先求MST然后DFS在枚举m-n+1条边。
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
const int MAXN=100+10;
int n,m,vis[MAXN*MAXN],fa[MAXN],dp[MAXN][MAXN];
int head[MAXN],len;
struct edge
{
int to,val,next;
}e[MAXN*MAXN];
void add(int from,int to,int val)
{
e[len].to=to;
e[len].val=val;
e[len].next=head[from];
head[from]=len++;
}
struct edge2
{
int from,to,val;
bool operator <(const edge2& x)const {
return val<x.val;
}
}e2[MAXN*MAXN];
int find(int cur)
{
return cur==fa[cur]? cur: fa[cur]=find(fa[cur]);
}
vector<int> nodes;
void dfs(int cur,int fa,int dis)
{
for(int i=0;i<nodes.size();i++)
{
int x=nodes[i];
dp[x][cur]=dp[cur][x]=max(dp[x][fa],dis);
}
nodes.push_back(cur);
for(int i=head[cur];i!=-1;i=e[i].next)
{
int id=e[i].to;
if(id!=fa) dfs(id,cur,e[i].val);
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
memset(dp,0,sizeof(dp));
memset(head,-1,sizeof(head));
len=0;
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&e2[i].from,&e2[i].to,&e2[i].val);
vis[i]=false;
}
//kruskal
int mstlen=0,mstlen2=9999999;
sort(e2,e2+m);
for(int i=1;i<=n;i++)
fa[i]=i;
for(int i=0;i<m;i++)
{
int x=e2[i].from,y=e2[i].to;
int root_x=find(x),root_y=find(y);
if(root_x==root_y) continue;
fa[root_x]=root_y;
add(x,y,e2[i].val);
add(y,x,e2[i].val);
mstlen+=e2[i].val;
vis[i]=true;
}
nodes.clear();
dfs(1,-1,0);
for(int i=0;i<m;i++)
{
if(vis[i]) continue;
mstlen2=min(mstlen2,mstlen-dp[ e2[i].from ][ e2[i].to ]+e2[i].val);
}
printf("%d %d\n",mstlen,mstlen2);
}
return 0;
}