Reverse disjoint-set (zoj 3261, hdoj 4496)

estimated 3261 Connections in Galaxy War

Subject to the effect: there are channel contact between some of the planet in the galaxy, yet another dimension of the monster destroyed some contact. So when some planet needs help, you need to determine what I can find a direct or indirect contact of the planet, and the power of the planet are all connected to the planet's largest planet. If there is such a planet, the planet's number is output, if there are multiple planets is the biggest, the smallest output that number. If you can not find such a planet, then "-1."
In the input, first inputs the number of planets n, n is the number of the second row, represents the power of each planet. The next line m is an integer representing the number of all links, the following is m lines of two integers, indicating which links have two planets. The next line is an integer q, represents the number of the processing, there are two cases:
first is: destroy ab denotes a destroyed, the connection between the b
The second is: Query whether a planet presents to ask the help of a

Solution: We are familiar with disjoint-set effect only plus side, disjoint-set and did not remove the effect of side. This problem began to get a look ignorant force , can not start, then see dalao code and found it to be the reverse disjoint-set, forward edge is deleted, if the reverse is the plus side of view, then, ah, is it not, and check set it?
Reverse meant here is that first off-line processing of all the action, and then reverse processing operations, when read, delete all sides to not add to the disjoint-set, the reverse process, the encounter "destroy" will be added to the side and check focus.
dalao practice is the relationship with the map and number of storage side, and then used an array of records which edge is to be deleted, a very clever combination of numbers and edges.

AC Code:

#include <iostream>
#include <map>
#include <string.h>
#include <algorithm>
#include <stdio.h>
using namespace std;
const int MAX=10001;
int power[MAX];//每个行星的战斗力
map<int,int>mp[MAX];//存边,以及边的编号
int used[2*MAX];//与map相结合,记录哪条边需要删除
int parent[MAX];
int ans[5*MAX];
int n;
struct edge//记录边,方便通过下标查询连接两个边的节点
{
    int x;
    int y;
}edges[2*MAX];
struct ques//记录问题,如果是destroy ,mark 记为1,如果是query,mark记为0
{
    int mark;
    int x;
    int y;
}que[5*MAX];
struct re//要求的最大力量和最小的编号
{
    int height;
    int num;
}res[MAX];
void init()//初始化
{
    memset(used,0,sizeof(used));
    for(int i=0;i<n;i++)
    {
        parent[i]=i;
        res[i].height=power[i];
        res[i].num=i;
        mp[i].clear();
    }
}
int find_root(int x)
{
    return parent[x]==x ? x : parent[x]=find_root(parent[x]);
}
void unite(int x,int y)
{
    x=find_root(x);
    y=find_root(y);
    if(x!=y)
    {
        parent[x]=y;
        if(res[x].height>res[y].height)
        {
            res[y].height=res[x].height;
            res[y].num=res[x].num;
        }
        else
        if(res[x].height==res[y].height&&res[x].num<res[y].num)
                res[y].num=res[x].num;
    }
}
int main()
{
    int flag=0;
    while(scanf("%d",&n)==1)
    {
        if(!flag)
            flag=1;
        else
            printf("\n");
        for(int i=0;i<n;i++)
            scanf("%d",&power[i]);
        init();
        int m;
        scanf("%d",&m);
        for(int i=0;i<m;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            if(x>y)
                swap(x,y);
            mp[x][y]=i;
            edges[i].x=x;
            edges[i].y=y;
        }
        int q;
        scanf("%d",&q);
        for(int i=0;i<q;i++)
        {
            char query[15];
            scanf("%s",query);
            if(query[0]=='q')
            {
                scanf("%d",&que[i].x);
                que[i].mark=0;
            }
            else
            {
                int x,y;
                scanf("%d%d",&x,&y);
                if(x>y)
                    swap(x,y);
                used[mp[x][y]]=1;//记录被删掉的边
                que[i].x=x;
                que[i].y=y;
                que[i].mark=1;
            }
        }
        for(int i=0;i<m;i++)//将没被删除的边先合并成集合
        {
            if(used[i])
                continue;
            else
                unite(edges[i].x,edges[i].y);
        }
        int t=0;
        for(int i=q-1;i>=0;i--)
        {
            if(!que[i].mark)//询问是否能找到帮助
            {
                int tmp=find_root(que[i].x);
                if(power[que[i].x]<res[tmp].height)
                    ans[t++]=res[tmp].num;
                else
                    ans[t++]=-1;
            }
            else
                unite(que[i].x,que[i].y);//将删除边转化为合并边
        }
        for(int i=t-1;i>=0;i--)
            printf("%d\n",ans[i]);
    }
}

hdoj 4496 D-City

Topic effect: a monster to involve the entire city of contact D completely destroyed, the output of questions asked how many points left to destroy blocks in a contact time. If and only if they are directly or indirectly connected to each other, two points in the same connection block.

Solution: ibid title as offline processing, but this problem is relatively simple, because it is "completely destroyed", so the output is always the last number of nodes. This problem exists edge first number stored two-dimensional array side, an open edge [MAX] [2] array, contact [i] [0], the second number is present edge [i] [1] in the ( this deposit side method good clever oh, forgive a rookie never seen the world ).

Do this problem when it found an interesting thing:
Scanf ( "% D% D", & n-, & m) 2 return value (if it's correct)
when the EOF is encountered, return value is -1, then It can be used to determine input ~ scanf. ~ Here is the inverse of the symbol, then the inverse complement of -1 to 0, the condition can be determined as a cycle.
At that time the scanf ( "% d% d" , & n, & m) is set to the return value of 1, WA the N hair. . .
In particular, see dalao Comments (about the scanf)

AC Code:

#include <iostream>
#include <map>
#include <stdio.h>
using namespace std;
const int MAX=10001;
int parent[MAX];
int edge[10*MAX][2];
int ans[10*MAX];
int n,m;
void init()
{
    for(int i=0;i<=n;i++)
    {
        parent[i]=i;
    }
}
int find_root(int x)
{
    return parent[x]==x ? x : parent[x]=find_root(parent[x]);
}
bool unite(int x,int y)
{
    x=find_root(x);
    y=find_root(y);
    if(x!=y)
    {
        parent[y]=x;
        return true;
    }
    return false;
}
int main()
{
    while(scanf("%d%d",&n,&m)==2)
    {
        int city=n;
        init();
        for(int i=0;i<m;i++)
        {
            scanf("%d%d",&edge[i][0],&edge[i][1]);
        }
        for(int i=m-1;i>=0;i--)
        {
            if(unite(edge[i][0],edge[i][1]))
                ans[i]=city--;
            else
                ans[i]=city;
        }
        for(int i=0;i<m;i++)
            printf("%d\n",ans[i]);
    }
}
Published 32 original articles · won praise 12 · views 1387

Guess you like

Origin blog.csdn.net/qq_18873031/article/details/99678551