Tourism

Keywords: Programming

The main idea of the topic

Links: https://www.nowcoder.com/acm/contest/177/B
Source: Niuke.com

During the summer vacation, I'm going to travel.

In the poor plan, pitiful people plan to visit nnn scenic spots, which are connected by mmm two-way roads (that is, any two scenic spots can be reached directly or indirectly by road). The length of road iii is 2i2^i2i.

Because only 111 of the nnn scenic spots are near the airport, it's a pity to make a plan to start at 111, travel along the road, and finally return to 111. At the same time, because each road has a different landscape, so pity wants to go through each road at least once in this plan (as long as you go in one direction, even if you go through this road).

Let the fatigue degree of a tour plan be the sum of the walking length (the edge length of many passes is calculated many times). Poor people want to calculate the minimum fatigue degree of all the tour plans that meet the conditions.

100% of the data are 1 < n,m < 5 1051 n,m 5 10 51 n,m 5 105.

Analysis

First of all, this question must go through every side.

Then the problem is transformed into "how to add the edge with the least weight to make the graph an Eulerian loop".

What graph is the Euler circuit?

In a graph with even degrees of entry at each point, we can go back to the starting point from one point only by traversing all edges once.

The problem becomes "how to add the edge with the smallest weight so that every point in the graph has an even degree".

Re-examine the topic "The length of road iii is 2i2^i2i". "That is, we choose an edge I to join, even if we choose all the edges in front of us, their weights are not as large as the edge I. We think of greedy ideas and try to get as little as possible.

So the question becomes "How to select the edge to join the minimum spanning tree of the graph so that each point of the graph has a degree of 000."

We have determined that the edges of the minimum spanning tree are to be added, so what can be added to make the entry of each point even?

We consider that dfs traverses the minimum spanning tree and discuss whether it is even from each leaf node. If the leaf node is not even, then we add a leaf node from here to its father's side, and add 111 degrees to the leaf node and its father's node.

Then we have basically finished the analysis of this problem. We need to pay attention to some minor details. m < 5 105m 5 10 5m 5 105. We can't move so many bits left by using left shift symbols. We need to use fast power to solve this problem.

Reference code

//
//  main.cpp
//  B- Tourism
//
//  Created by Ted_Tong on 2018/10/14.
//  Copyright © 2018 Ted_Tong. All rights reserved.
//
 
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define maxm 500010
#define mod 998244353
#define ll long long
using namespace std;
int n,m,cnt_e,cnt_p,root,t,fa[maxm],ind[maxm],head[maxm];
bool vis[maxm];
ll ans;
struct edge{
    int u,v,w;
}edges[maxm*2];//edge holds the original graph
bool cmp(edge a,edge b){
    return a.w<b.w;
}
void add_e(int u,int v,int w){
    cnt_e++;
    edges[cnt_e].u=u;
    edges[cnt_e].v=v;
    edges[cnt_e].w=w;
}
struct path{
    int to,nxt,w;
}paths[maxm*2];//path stores the minimum spanning tree
void add_p(int u,int v,int w){
    cnt_p++;
    paths[cnt_p].to=v;
    paths[cnt_p].nxt=head[u];
    paths[cnt_p].w=w;
    head[u]=cnt_p;
}
int find(int x){
    if (fa[x]==x) {
        return fa[x];
    }
    return fa[x]=find(fa[x]);
}
ll quickPower(int b){
    ll res=1,base=2;
    while(b>0){
        if(b&1){
            res*=base;
            res%=mod;
        }
        base*=base;
        base%=mod;
        b>>=1;
    }
    return res;
}
void kruskal(){
    for (int i=1; i<=2*m; i++) {
        int fa_u=find(edges[i].u);
        int fa_v=find(edges[i].v);
        if (fa_u==fa_v) {
            continue;
        }
        add_p(edges[i].u,edges[i].v,edges[i].w);
        add_p(edges[i].v,edges[i].u,edges[i].w);
        fa[fa_v]=fa_u;
        t++;
        if (t==n-1) {
            root=find(fa_u);
            break;
        }
    }
}
void dfs(int pi,int u,int fa){
    for (int i=head[u]; i; i=paths[i].nxt) {
        int v=paths[i].to;
        if (!vis[v]) {
            vis[v]=1;
            dfs(i, v, u);
        }
    }
    if (ind[u]%2==1) {
        ind[u]++;
        ind[fa]++;
        ans=(ans+quickPower(paths[pi].w))%mod;
    }
    return;
}
int main() {
    scanf("%d%d",&n,&m);
    for (int i=1; i<=n; i++) {
        fa[i]=i;
    }
    for (int i=1; i<=m; i++) {
        int u,v;
        scanf("%d%d",&u,&v);
        add_e(u, v, i);
        add_e(v, u, i);
        ind[v]++;
        ind[u]++;
        ans=(ans+quickPower(i))%mod;
    }
    kruskal();
    vis[root]=1;
    dfs(0, root, 0);
    printf("%lld\n",ans);
    return 0;
}

Posted by HTF on Sun, 03 Feb 2019 02:51:16 -0800