暑期集训补题系列Day4--图论

Day4 – 图论

A - The Two Routes Codeforces 601A
https://blog.csdn.net/mengxiang000000/article/details/52261778
题目大意:

有n个城市,m条火车路,对于一个完全图来讲,如果这条路上要么建的是火车路 ,要么是正常路,火车路走火车,正常路走汽车。就是说,对于map【i】【j】,这条路要么是火车路,要么是正常路,问在不走重复城市的情况下(起点终点不算),两个人同时在城市1出发,目标是城市n,问最后到达的那个人走的最小路程,每条路长度为1.

思路:

1、对于完全图,map【1】【n】这条边,要么是火车路,要么是汽车路,如果是火车路,我们就求汽车路的最短路,如果是汽车路,我们就求火车路的最短路。

2、那么如果map【1】【n】==0,将图取反,跑Floyd(数据不大,取最优代码量);

#include
#include
#include
using namespace std;
int map[500][500];
int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        memset(map,0,sizeof(map));
        for(int i=0;i<m;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            map[x][y]=map[y][x]=1;
        }
        if(map[1][n]==1)
        {
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=n;j++)
                {
                    map[i][j]=1-map[i][j];
                }
            }
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                for(int k=1;k<=n;k++)
                {
                    if(map[j][i]==0||map[i][k]==0)continue;
                    if(map[j][k]==0)map[j][k]=map[j][i]+map[i][k];
                    map[j][k]=min(map[j][i]+map[i][k],map[j][k]);
                }
            }
        }
        if(map[1][n]==0)
        {
            printf("-1\n");
        }
        else printf("%d\n",map[1][n]);
    }
}

C - Cyclic Components Codeforces 977E
题目大意:求单圈环的个数【单圈环就是只有一个圈的环…】

题目分析:观察单圈环的可以发现它的一个性质每个点的度都是2

#include 
using namespace std;

#define f first
#define s second
#define ll long long
const int maxn=3e5;
vector<int>v[maxn];
int vis[maxn];
int ans,flag;
void dfs(int now,int fa)
{
    vis[now]=1;
    if(v[now].size()!=2)flag=1;
    for(auto i:v[now])
    {
    if(i==fa||vis[i])continue;
    dfs(i,now);
    }
}

int main()
{
    int n,m;
    cin>>n>>m;
    for(int i=0;i<m;i++)
    {
    int x,y;
    cin>>x>>y;

    v[x].push_back(y);
    v[y].push_back(x);
    }
    for(int i=1;i<=n;i++)
    {
    flag=0;
    int ok=0;
    if(!vis[i])dfs(i,-1),ok=1;
    if(flag==0&&ok==1)ans++;
    }
    cout<<ans;
    return 0;
}

当然,也可以用并查集解决。

#include 
using namespace std;

const int MAXN = 2e5 + 10;
int fa[MAXN], du[MAXN];
vector<int> anc[MAXN];
int n, m;

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

void merge(int a, int b) {
    int faA = find(a);
    int faB = find(b);
    if(faA != faB) {fa[faA] = faB;}
}

int main() {
    //freopen("input.txt", "r", stdin);
    for(int i = 1; i <= MAXN; i++) {fa[i] = i;}
    scanf("%d %d", &n, &m);
    int u, v;
    for(int i = 1; i <= m; i++) {
        scanf("%d %d", &u, &v);
        merge(u, v);
        du[u]++; du[v]++;
    }
    // important !!!
    for(int i = 1; i <= n; i++) {
        anc[find(i)].push_back(i);
    }
    int cnt = 0;
    for(int i = 1; i <= n; i++) {
        if(anc[i].size() > 2) {
            bool flag = true;
            int si = anc[i].size();
            for(int j = 0; j < si && flag; j++) {
                if(du[anc[i][j]] != 2) {flag = false;}
            }
            if(flag) {cnt++;}
        }
    }
    printf("%d\n", cnt);
    //fclose(stdin);
    return 0;
}

你可能感兴趣的:(暑期集训补题系列Day4--图论)