[AT_tenka1_2015_final_g] 天下一ゲーム

评价:感觉还是过于神秘了,暴力写的群魔乱舞,正解返璞归真。

暴力做法太多了,就不记录了。

我们考虑一个贪心,由于边权互不相同,我们把边按照边权从大到小排序,然后依次尝试满足当前边,这样显然是极其优秀的,因为你满足了当前边,后面的边的最小值仍未确定,也就是可以继续解决的。

而唯一可能影响情况的,就是当前边两个点都是第一次出现,这个操作就不是唯一的,而这个暴力解决就行了,因为这类边最多只有 \(\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';
}
posted @ 2025-01-18 15:08  ~Cyan~  阅读(17)  评论(0)    收藏  举报