评价:感觉还是过于神秘了,暴力写的群魔乱舞,正解返璞归真。
暴力做法太多了,就不记录了。
我们考虑一个贪心,由于边权互不相同,我们把边按照边权从大到小排序,然后依次尝试满足当前边,这样显然是极其优秀的,因为你满足了当前边,后面的边的最小值仍未确定,也就是可以继续解决的。
而唯一可能影响情况的,就是当前边两个点都是第一次出现,这个操作就不是唯一的,而这个暴力解决就行了,因为这类边最多只有 \(\frac{n}{2}\),所以复杂度是 \(O(2^{\frac{n}{2}})\)。(想到这个贪心就迎刃而解了)。
点击查看代码
#include<bits/stdc++.h>
#define fir first
#define sec second
#define mkp make_pair
#define lowbit(x) x&(-x)
using namespace std;
typedef pair<int,int> pir;
inline int read(){
int x=0,f=1; char c=getchar();
while(!isdigit(c)){if(c=='-') f=-1; c=getchar();}
while(isdigit(c)){x=x*10+(c^48); c=getchar();}
return x*f;
}
const int N=45,inf=1e9;
int n,m;
int mx[N],val[N];
struct edge{int u,v,w;}p[N*N];
inline bool cmp(edge a,edge b){
return a.w>b.w;
}
int s;
int num[N],vis[N],res[N];
signed main(){
n=read(),m=read();
for(int i=1;i<=m;i++){
int u=read(),v=read(),w=read();
mx[u]=max(mx[u],w);
mx[v]=max(mx[v],w);
p[i]={u,v,w};
}
sort(p+1,p+m+1,cmp);
for(int i=1;i<=m;i++){
int u=p[i].u,v=p[i].v;
if(vis[u]||vis[v]) continue;
num[s++]=u;
vis[u]=1,vis[v]=1;
}
int st=1<<s;
int ans=-1;
for(int msk=0;msk<st;msk++){
for(int i=1;i<=n;i++) val[i]=inf;
for(int i=0;i<s;i++) if(msk>>i&1) val[num[i]]=mx[num[i]];
int cnt=0;
for(int i=1;i<=m;i++){
int u=p[i].u,v=p[i].v,w=p[i].w;
if((val[u]==inf)^(val[v]==inf)){
if(val[u]==inf) val[u]=w;
if(val[v]==inf) val[v]=w;
cnt++;
}
}
if(ans<cnt){
ans=cnt;
for(int i=1;i<=n;i++) res[i]=val[i];
}
}
for(int i=1;i<=n;i++) cout<<res[i]<<'\n';
}