并查集入门题——UVALive-3644化合爆炸物+UVALive-3027

X-Plosives

是数据增强过了吗,还是评测系统出了问题,已AC的代码现在还WA
思路:
每种化学元素就是一个,每种化合物就是一个,产生爆炸物的情况就是图中产生了一个环。
并查集,来维护图中的连通分量。

#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ms0(a) memset(a,0,sizeof(a))
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;

const int maxn = 1e6;
int fa[maxn];

int find(int x)
{
    return x==fa[x]?x:fa[x]=find(fa[x]);
}

void init()
{
    for(int i=0;i<maxn;i++)
        fa[i]=i;
}

int x,y,ans=0;
int main(){
    init();
    while (~scanf("%d",&x))
    {
        if(x!=-1)
            scanf("%d",&y);
        else
        {
            printf("%d\n",ans);
            ans=0;
            init();
        }
        int fx = find(x),fy=find(y);
        if(fx!=fy)
            fa[fx]=fy;
        else
            ans++;
    }
    return 0;
}

Corporative Network

两种操作:
I u v :
u的父亲节点为v,边权为|u-v|(mod)1000
E u:
查询u到根节点的距离。

思路:
不要直接存储节点u到根节点的距离,否则可能产生”牵一发而动全身“的情况———一次(I,u,v)操作,更新很多节点的信息。
而间接地选择存贮到父节点的距离,之后查询的时候,一直查询到根节点为止。

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ms0(a) memset(a,0,sizeof(a))
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;

const int maxn = 2e4+10;
int ncase,n,u,v,fa[maxn],d[maxn];
char s[10];

void init()
{
    for(int i=1;i<=n;i++)
        fa[i]=i;
    ms0(d);
}

int find(int x)
{
    return x==fa[x]?x:fa[x]=find(fa[x]);
}

void merge(int x,int y)
{
    fa[x]=y;
    d[x]= abs(x-y)%1000;
}


int main(){
    cin>>ncase;
    while (ncase--)
    {
        
        scanf("%d",&n);
        while (scanf("%s",s) && s[0]!='O')
        {
            if(s[0]=='E')
            {
                scanf("%d",&u);
                int sum=0;
                for(int i=u;i;i=fa[i])
                    sum+=d[i];
                printf("%d\n",sum);
            }
            else
            {
                scanf("%d%d",&u,&v);
                merge(u,v);
            }
        }
    }
    return 0;
}

Wireless Network

Description:
有一个计算机网络的所有线路都坏了,网络中有n台计算机,现在你可以做两种操作,修理(O)和检测两台计算机是否连通(S),只有修理好的计算机才能连通。连通有个规则,两台计算机的距离不能超过给定的最大距离D(一开始会给你n台计算机的坐标)。检测的时候输出两台计算机是否能连通。

两种操作:

  1. “O p” 修理p这台计算机,
  2. “S p q” 检查是否连通。

思路:
每修一台计算机,就和vector repaired;里的计算机hebing(如果距离小于D的话),然后将这个点再加入vector repaired;。
这个时间复杂度是可以承受的。

#include
#include
#include
#include
#include
#include
#include
#include
#define ll long long
using namespace std;
const int maxn= 1010;
int fa[maxn],n,d;

struct dot{
    int x,y,id;
}t[maxn];
vector<dot> repaired;
bool inDistance(dot a,dot b){
    double dis = sqrt(pow((a.x-b.x),2)+pow((a.y-b.y),2));
    return dis<=d;
}


int find(int x){
    return (x==fa[x])?x:fa[x]=find(fa[x]);
}

void merge(dot a,dot b){
    int fx=find(a.id),fy=find(b.id);
    if(fx!=fy) fa[fx]=fy;
}

int main(){
    cin>>n>>d;
    for(int i=1;i<=n;i++) {
        fa[i]=i;
        int x,y;
        scanf("%d%d",&x,&y);
        t[i].x=x;t[i].y=y;t[i].id=i;
    }
    char op[10];
    while(~scanf("%s",op)){
        if(op[0]=='O'){
            int id;
            scanf("%d",&id);
            for(int i=0;i<repaired.size();i++){
                if(inDistance(repaired[i], t[id])){
                    merge(repaired[i], t[id]);
                }
            }
            repaired.push_back(t[id]);
        }else{
            int id1,id2;
            scanf("%d%d",&id1,&id2);
            if(find(id1)==find(id2)) printf("SUCCESS\n");
            else printf("FAIL\n");
        }
    }
    return 0;
}

你可能感兴趣的:(树的森林,#,并查集)