求助QwQ
查看原帖
求助QwQ
127925
Kio_楼主2020/11/6 21:05

思路和第一篇题解差不多......但只拿到了40pts40 pts

求大佬答疑qwq

#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 50020;
struct pt{
    int s,t,c,col;
}line[maxn];
inline bool cmp(pt a,pt b){return a.c<b.c;}
int faj[maxn];
int n,m,need;
int ans;
int find(int x){
    return x==faj[x]?x:faj[x] = find(faj[x]);
}
inline void merge(int x,int y){faj[find(x)] = faj[find(y)];}

void add(int mid){for(int i=1;i<=n;i++)if(line[i].col) line[i].c+=mid;}//通过给黑边加权,控制白边数量
void minus(int mid){for(int i=1;i<=n;i++)if(line[i].col) line[i].c-=mid;}//操作完后还要减回来
int kruskal(int &ans,int mid){

    for(int i=1;i<=n;i++) faj[i] = i;
    int sum=0,cnt=0;
    for(int i=1;i<=m;i++){
        int u = line[i].s, v = line[i].t;
        if(find(u) != find(v)){
    //      printf("%d\n",line[i].c);
            cnt++;
            merge(u,v),ans+=line[i].c;
            if(!line[i].col) sum++;
            else ans-=mid;
            if(cnt==n-1)break;
        }
    }
    return sum;
}
int read(){
    int num=0;
    char c=getchar();
    while(c<'0'||c>'9')c=getchar();
    while('0'<=c&&c<='9')num=num*10+c-'0',c=getchar();
    return num;
}
int main(){
    n=read(),m=read(),need=read();
    for(int i=1;i<=m;i++){
        line[i].s = read();
        line[i].s++;
        line[i].t = read();
        line[i].t++;
        line[i].c = read();
        line[i].col = read();
    }
    int l=-120,r=120;
    int ans=0;
    while(l<r){
    //  printf("%d %d\n",l,r);
        int mid = (l+r)>>1;
        add(mid);
        sort(line+1,line+n+1,cmp);
        ans=0;
        int cnt = kruskal(ans,mid);
        if(cnt==need){
            printf("%d",ans);
            return 0;
        }
        if(cnt>need) r=mid-1;
        else l=mid+1;
        minus(mid);
    }
    printf("%d",ans);
    return 0;
}
2020/11/6 21:05
加载中...