N - Wires(dfs 图论 离散化)

题目链接:https://codeforces.com/contest/1250/problem/N
题意:给定一个图,点从1到1e9,边有2e5,修改一些边,使得最后所有边都在同一集合
题解:由于点比较多,需要离散化;对于每个联通块,把dfs过程中把每个联通块的最后遍历的点以及所在的边进行修改即可。

#include<bits/stdc++.h>
using namespace std;
const int maxn=200010;

int n;
struct edge{
    int v,nxt,id;
}e[maxn*2];
int head[maxn],tot;
struct node{
    int x,y;
}a[maxn];
int b[maxn*2],bn;
int fa[maxn*2];
bool vis[maxn];
int pos,id;
void init(){
    tot=0;
    for(int i=0;i<=2*n;i++) head[i]=-1,vis[i]=0;//2*n debug了好一会。。
}
void addedge(int u,int v,int id){
    e[tot].v=v;e[tot].id=id;
    e[tot].nxt=head[u];head[u]=tot++;
}

void dfs(int u,int p){
    vis[u]=1;
    if(head[u]!=-1){
        pos=u;id=e[head[u]].id;
    }
    for(int i=head[u];~i;i=e[i].nxt){
        int v=e[i].v;
        if(v==p||vis[v]) continue;
        dfs(v,u);
    }
    return;
}
struct Ans{
    int id,fr,to;
}ans[maxn*2];
int main(){
    int t;scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        bn=0;
        int x,y,u,v;
        for(int i=1;i<=n;i++){
            scanf("%d%d",&x,&y);
            a[i].x=x;a[i].y=y;
            b[bn++]=x;b[bn++]=y;
        }
        sort(b,b+bn);
        bn=unique(b,b+bn)-b;//离散化
        init();
        int mx=0;
        for(int i=1;i<=n;i++){
            x=a[i].x,y=a[i].y;
            //注意这里要使起始点为1
            u=lower_bound(b,b+bn,x)-b+1;
            v=lower_bound(b,b+bn,y)-b+1;
            fa[u]=x;fa[v]=y;
            addedge(u,v,i);addedge(v,u,i);
            mx=max(mx,max(u,v));
        }
        dfs(1,1);
        int tt=0;
        for(int i=2;i<=mx;i++){//《=bn
            if(vis[i]) continue;
            pos=-1;
            dfs(i,i);
            if(pos==-1) continue;
            ans[tt].id=id;ans[tt].fr=fa[pos];ans[tt++].to=fa[1];
        }
        printf("%d\n",tt);
        for(int i=0;i<tt;i++){
            printf("%d %d %d\n",ans[i].id,ans[i].fr,ans[i].to);
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值