#include
#include
#include
#include
#include
#define fzhead EDGE(int _from, int _to, int _val, int _next,int _vis)
#define fzbody from(_from), to(_to), val(_val), next(_next) ,vis(_vis)
#define mst(x,a) memset(x,a,sizeof(x))
#define pb push_back
#define mp make_pair
#define For(i,x,y) for(register int i=(x); i<=(y); i++)
using namespace std;
typedef long long ll;
const int INF=0x3f3f3f3f;
const int maxn=100+10;
const int maxm=1e4+10;
vector<int>p[maxn];
struct EDGE
{
int from,to,next,val;
int vis;
EDGE(){
}
fzhead:fzbody{
}
bool operator <(const EDGE&a)const
{
return val<a.val;
}
}e[maxm];
int cnt,n,m;
int head[maxn], f[maxn];//vis[maxm],
int dp[maxn][maxn];
void add(int bg, int to, int val)
{
e[++cnt]=EDGE(bg,to,val,head[bg],0);
head[bg]=cnt;
}
int find(int x)
{
if(x==f[x])return f[x];
return f[x]=find(f[x]);
}
int main()
{
int t;
scanf("%d", &t);
while(t--)
{
cnt=0;
mst(head,-1);mst(e,0);mst(dp,0);//mst(vis,0);
scanf("%d%d", &n,&m);
int a,b,val;
For(i,1,n)
{
f[i]=i;
p[i].clear();
p[i].pb(i);
}
For(i,1,m)
{
scanf("%d%d%d",&a,&b,&val);
add(a,b,val);
}
sort(e+1,e+1+cnt);
ll ans=0;
int cnt1=0;
For(i,1,cnt)
{
a=find(e[i].from);b=find(e[i].to);
if(a==b)continue;
ans+=e[i].val;
f[a]=b;
e[i].vis=1;
//vis[++cnt1]=i;
int len1=p[a].size();
int len2=p[b].size();
For(j,0,len1-1)
{
For(k,0,len2-1)dp[p[a][j]][p[b][k]]=dp[p[b][k]][p[a][j]]=e[i].val;
//因为边权说排序了的,所以越往后,边权就越大,
//直接更新集合里的点到各点之前的最大边权
}
For(j,0,len1-1)p[b].pb(p[a][j]);
//把祖先a集合里的所有点,合并到集合b里去。
if(cnt1==n-1)break;
}
ll res=INF;
int flag=1,tot=1;
For(i,1,cnt)
{
if(!e[i].vis)
res=min(res,ans+e[i].val-dp[e[i].from][e[i].to]);
}
if(res>ans)printf("%lld\n",ans);
else printf("Not Unique!\n");
}
return 0;
}
要你求次小生成树,看次小生成树是不是等于最小生成树,如果等于就NOT unique。
#include
#include
#include
#include
#define fzhead EDGE(int _from, int _to, int _val, int _next)
#define fzbody from(_from), to(_to), val(_val), next(_next)
#define mst(x,a) memset(x,a,sizeof(x))
#define For(i,x,y) for(register int i=(x); i<=(y); i++)
using namespace std;
typedef long long ll;
const int maxn=100+10;
const int maxm=1e4+10;
struct EDGE
{
int from,to,next,val;
EDGE(){
}
fzhead:fzbody{
}
bool operator <(const EDGE&a)const
{
return val<a.val;
}
}e[maxm];
int cnt,n,m;
int head[maxn],vis[maxm], f[maxn];
void add(int bg, int to, int val)
{
e[++cnt]=EDGE(bg,to,val,head[bg]);
head[bg]=cnt;
}
int find(int x)
{
if(x==f[x])return f[x];
return f[x]=find(f[x]);
}
int main()
{
int t;
scanf("%d", &t);
while(t--)
{
cnt=0;
mst(head,-1);mst(e,0);mst(vis,0);
scanf("%d%d", &n,&m);
int a,b,val;
For(i,1,n)f[i]=i;
For(i,1,m)
{
scanf("%d%d%d",&a,&b,&val);
add(a,b,val);
}
sort(e+1,e+1+cnt);
ll ans=0;
int cnt1=0;
For(i,1,cnt)
{
a=find(e[i].from);b=find(e[i].to);
if(a==b)continue;
ans+=e[i].val;
f[a]=b;
vis[++cnt1]=i;
if(cnt1==n-1)break;
}
//第一次求
ll tmp=0;
int flag=1,tot=1;
//cout<
For(i,1,cnt1)
{
tmp=0;tot=1;
For(j,1,n)f[j]=j;
For(j,1,cnt)
{
if(j==vis[i])continue;//枚举不在最小生成树的边,再求最小生成树。
a=find(e[j].from);b=find(e[j].to);
if(a==b)continue;
tmp+=e[j].val;
f[a]=b;
tot++;//
}
// cout<
if(tmp==ans&&tot==n){
flag=0;break;}
}
if(flag)printf("%lld\n",ans);
else printf("Not Unique!\n");
}
return 0;
}