1.数连通分量(并查集)

PAT1013 Battle Over Cities

当删除其中一个顶点及其相关的边之后,计算出剩下的图的连通分量,那么增加的边就应该是求出的连通分量-1

法1:每次dfs前判断visit[i]==0;

void dfs(int s) {
    visit[s] = 1;
    for(int i = 1; i<=n; ++i)
	if(g[s][i]==1&&visit[i]==0)dfs(i);
}
...main:
for (i = 0; i < k; ++i) {
    sum = 0;cin >> m;
    fill(visit.begin(),visit.end(),0);
    visit[m] = 1;
    for (j = 1; j<=n; ++j)
        if (visit[j] == 0){dfs(j);sum++;}
    printf("%d\n", sum-1);
}

法2:数根结点father[v]==v;

while(K--){
    int v;int num=0;
    scanf("%d",&v);
    iota(father,father+N+1,0);//初始化并查集
    for(int i=1;i<N+1;++i)
        if(i!=v)for(int j:graph[i])
            if(j!=v)uni(i,j);
    for(int i=1;i<=N;++i)
        if(i!=v&&father[i]==i)
            ++num;
    printf("%d\n",num-1);
}

Leetcode947

在二维平面上将石头放置在一些整数坐标点上。每个坐标点上最多只能有一块石头。现在,一个move将会移除与网格上的另一块石头共享一列或一行的一个石头。
int removeStones(vector<vector<int>>& stones) {
    if(stones.size() <= 1) return 0;
    int res = stones.size(), len = stones.size();
    vector<int> p(len,-1);
    for(int i =0;i < len;i++){
        for(int j = i+1;j < len;j++){
            if(stones[j][0] == stones[i][0] || stones[j][1] == stones[i][1])
                u(p, i, j);
        }
    }
    for(auto e : p){
        if(e == -1) res--;
    }
    return res;
}

2.有关是对边dfs还是点dfs

PAT1034

给出多个人之间的通话长度,按照这些通话将他们分成若干个组,各个组的总权值是该组内所有通话长度之和,每个人的权值是其参与的所有通话长度之和。求组数和组内通话最长的

每个点至少有一个连线,故可以对边搜数量关系的运用:边权和=点权和/2

之后的操作--PAT2019春7-3 Telefraud Detection

电信诈骗判断嫌疑犯,若犯人之间通过话说明是一个团伙
for(i=1;i<=n;++i)
    if(sus[i]==1)
        for(j=i+1;j<=n;++j)
            if(sus[j]==1&&g[i][j]>0&&g[j][i]>0)uni(i,j);
w=1;
for(i=1;i<=n;++i){
    if(sus[i]==1){
        if(mp[findf(i)]==0){
            mp[findf(i)]=w;
            gang[w].push_back(i);
            w++;
        }//将联通分量转换为gang
        else gang[mp[findf(i)]].push_back(i);
    }
}

PAT1021

给定N个结点和N-1条边,问能否构成一棵树,如果能,则输出作为树的根节点时使得整棵树深度最大的结点,如果不能,输出这个图中有几个连通分量。

能否构成树,要么有>1个连通分量,要么有环

3.Hamiltonian Cycle

(1)是否是N+1个点。 (2)除起点外,每个点是否只出现了1次 (3)经过的边是否存在 (4)起点是否等于终点

注意剔除重复点时要用set(往往隐含)

void check(int index) {
    int sum = 0, cnt, flag = 1;
    scanf("%d", &cnt);
    set<int> s;
    vector<int> v(cnt);
    for (int i = 0; i < cnt; i++) {
        scanf("%d", &v[i]);
        s.insert(v[i]);
    }
    for (int i = 0; i < cnt - 1; i++) {
        if(e[v[i]][v[i+1]] == 0) flag = 0;//3
        sum += e[v[i]][v[i+1]];
    }
    if (flag == 0)
    printf("Path %d: NA (Not a TS cycle)\n", index);
    else if(v[0]!=v[cnt-1]||s.size()!=n)//4,2
    printf("Path %d: %d (Not a TS cycle)\n", index, sum);
    else if(cnt != n + 1)printf("Path %d: %d (TS cycle)\n", index, sum);//1
    else printf("Path %d: %d (TS simple cycle)\n", index, sum);
}

4.dfs结构总结

void dfs(int x){
    temp.push_back(x);
    if (pre[x][0] == -1){
        ......
    }
    for(int i=0;i<pre[x].size();i++){
        dfs(pre[x][i]);
    }
    temp.pop_back();
}
posted @ 2019-12-13 20:44  飞翔的菜鸟123  阅读(110)  评论(0编辑  收藏  举报