並查集入門題——UVALive-3644化合爆炸物+UVALive-3027

X-Plosives

是數據增強過了嗎,還是評測系統出了問題,已AC的代碼現在還WA
思路:
每種化學元素就是一個,每種化合物就是一個,產生爆炸物的情況就是圖中產生了一個環。
並查集,來維護圖中的連通分量。

#include<stdio.h>
#include<iostream>
#include<cmath>
#include<math.h>
#include<string>
#include<string.h>
#include<algorithm>
#include<queue>
#include<vector>
#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<stdio.h>
#include<iostream>
#include<cmath>
#include<math.h>
#include<string>
#include<string.h>
#include<algorithm>
#include<stack>
#include<queue>
#include<vector>
#include<map>
#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<dot> repaired;裏的計算機hebing(如果距離小於D的話),然後將這個點再加入vector<dot> repaired;。
這個時間複雜度是可以承受的。

#include<stdio.h>
#include<iostream>
#include<cmath>
#include<math.h>
#include<string>
#include<string.h>
#include<algorithm>
#include<vector>
#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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章