欧拉回路

.下面是判有没有欧拉路或欧拉回路的,用并查集来做,判断是否联通,注意欧拉回路包括欧拉路。

无向图:回路:所有点度都是偶数,路:起点终点是奇数

有向图:回路:所有点的入度等于出度,路:起点或终点,一个点入度比出度大一,一个点出度比入度大一。

#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;
const int maxm = 1e3 + 5;
int indeg[maxm], pa[maxm], ran[maxm], isin[maxm];

void make_set(int x){
pa[x] = x;
ran[x] = 0;
}

int findx(int x)
{
    int r = x, temp;
    while(pa[r] != r) r = pa[r];
    while(x != r)
    {
        temp = pa[x];
        pa[x] = r;
        x = temp;
    }
    return x;
}
void unio(int x, int y) {
x = findx(x);
y = findx(y);
if(x == y)return ;
if(ran[x] > ran[y]) {
pa[y] = x;
}
else {
pa[x] = y;
if(ran[x] == ran[y]) {
ran[y]++;
}
}
}
int n, m, x, y;
int main() {
while(~scanf("%d", &n)) {
    if(n == 0) break;
    scanf("%d", &m);
    memset(indeg, 0, sizeof(indeg));
//    memset(outdeg, 0, sizeof(outdeg));
    memset(isin, 0, sizeof(isin));
    for(int i = 1; i <= n; i++) {
        make_set(i);
    }
    for(int i = 1; i <= m; i++) {
        scanf("%d%d", &x, &y);
        unio(x, y);
        indeg[x]++;
        indeg[y]++;
        isin[x] = isin[y] = 1;
    }
    int num = 0;
    for(int i = 1; i <= n; i++) {
        if(isin[i] && findx(i) == i)
        num++;
    }
    if(num > 1) {
        printf("0
");
        continue;
    }
    int flag = 0;
    for(int i = 1; i <= n; i++) {
        if(isin[i] && indeg[i] % 2) {
            flag = 1;
        }
    }
    if(flag) printf("0
");
    else printf("1
");
}


return 0;
}
//这种类型是看存不存在欧拉回路或者道路,大部分是并查集的知识。

 题目:john's trip

https://vjudge.net/contest/280900#problem/G

 Johnny 有了一台新车,他想去访问他所有的朋友(赤裸裸的炫耀?),他的朋友有很多,住在城市中的街道上,于是他就开始规划自己的路了,在这个城市中有很多街道,他想找一个路径,这个路径经过一个街道仅一次,但能访问完他所有的朋友,他从他父母家出发,并且回来时也必须在他父母家。

  在这个城市中,一共有N(N < 1995)个街道,共有M(M <= 44)个转折点,转折点就是一个街道的两端,每条街道和转折点的编号都不同。如果在一个转折点有多种选择,他会优先选择街道编号比较小的。

  让你帮忙写一个程序,找到这个路径,如果找不到就打印“Round trip does not exist.”,从 1 号转折点出发,最后必须回到 1 号转折点,经过每条街道仅一次,访问完他所有的朋友,街道是双向的,但是不能掉头。

//这个题目edge存的是出发点与道路的长度,用vis数组标记是否存过,按字典序的话因为本来就是0-len,所以就是字典序排的
//注意这个dfs是到底才开始回溯,所以是反的

#include<cstdio> #include<algorithm> #include<cstring> using namespace std; typedef pair<int, int> pii; const int maxm = 2000; int deg[50], isin[50], edge[50][maxm]; int road[maxm], len, vis[maxm]; int now; //void make_set(int x){ // pa[x] = x; //} //int findx(int x) { //if (x != pa[x]) { //pa[x] = findx(pa[x]); //} //return pa[x]; //} // //void unio(int x, int y) { //x = findx(x); //y = findx(y); //if(x == y)return ; //pa[x] = y; //} void dfs(int x) { int i; for(i = 1; i <= len;i++) {
//i是指街道的编号。
if(edge[x][i] && !vis[i]){ // printf("%d ", i); vis[i] = 1; dfs(edge[x][i]); road[++now] = i; } // printf("%d ", i); } } int x, y, t, home; int main() { while(~scanf("%d%d", &x, &y)) { if(x == 0 && y == 0) break; len = -1; home = min(x, y); // for(int i = 1; i < maxm; i++) { // make_set(i); // } memset(deg, 0, sizeof(deg)); memset(isin, 0, sizeof(isin)); memset(edge, 0, sizeof(edge)); memset(vis, 0, sizeof(vis)); while(x != 0 && y != 0) { scanf("%d", &t); len = max(len, t); deg[x]++; deg[y]++; isin[x] = isin[y] = 1; // edge[x][t] += y; // edge[y][t] += x; edge[x][t] = y; edge[y][t] = x; scanf("%d%d", &x, &y); } int flag = 0; for(int i = 1; i <= 48; i++) { if(isin[i] && deg[i] % 2) { flag = 1; break; } } if(flag) { printf("Round trip does not exist. "); continue; } now = 0; dfs(home); // sort(road + 1, road + now + 1); for(int i = now; i > 0; i--) { if(i == now) printf("%d", road[i]); else printf(" %d", road[i]); } printf(" "); } return 0; }

https://vjudge.net/contest/280900#problem/P

The necklace

这个题目和上面那个差不多。


#include<cstdio> #include<algorithm> #include<cstring> using namespace std; typedef pair<int, int> pii; const int maxm = 55; int pa[maxm], deg[maxm], isin[maxm], edge[maxm][maxm]; pii road[1005]; int now; void make_set(int x){ pa[x] = x; } int findx(int x) { if (x != pa[x]) { pa[x] = findx(pa[x]); } return pa[x]; } void unio(int x, int y) { x = findx(x); y = findx(y); if(x == y)return ; pa[x] = y; } void dfs(int x) { int i; for(i = 1; i <= 50;i++) { if(edge[x][i]){ // printf("%d ", i); edge[x][i]--; edge[i][x]--; dfs(i); road[now++] = make_pair(x, i);
//这个题目是要打印每条路的两个端点。 }
// printf("%d ", i); } } int t, n, x, y; int main() { scanf("%d", &t); int index = 0; while(t--) { scanf("%d", &n); int home; for(int i = 1; i <= 50; i++) { make_set(i); } memset(deg, 0, sizeof(deg)); memset(isin, 0, sizeof(isin)); memset(edge, 0, sizeof(edge)); while(n--) { scanf("%d%d", &x, &y); unio(x, y); home = x; deg[x]++; deg[y]++; edge[x][y]++; edge[y][x]++; isin[x] = isin[y] = 1; } int ant = 0; // printf("%d ", ant); for(int i = 1; i <= 50; i++) { if(isin[i] && findx(i) == i) { ant++; } } if(ant > 1) { printf("Case #%d ", ++index); printf("some beads may be lost "); continue; } int flag = 0; for(int i = 1; i <= 50; i++) { if(isin[i] && deg[i] % 2 != 0) { flag = 1; break; } } if(flag) { printf("Case #%d ", ++index); printf("some beads may be lost "); } else { now = 1; dfs(home); printf("Case #%d ", ++index); for(int i = now - 1; i > 0; i--) { printf("%d %d ", road[i].first, road[i].second); } printf(" "); } } return 0; }
原文地址:https://www.cnblogs.com/downrainsun/p/10323342.html