Tourism【codeforces 1200E】

E. Tourism
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Alex decided to go on a touristic trip over the country.

For simplicity let's assume that the country has nn cities and mm bidirectional roads connecting them. Alex lives in city ss and initially located in it. To compare different cities Alex assigned each city a score wiwi which is as high as interesting city seems to Alex.

Alex believes that his trip will be interesting only if he will not use any road twice in a row. That is if Alex came to city vv from city uu, he may choose as the next city in the trip any city connected with vv by the road, except for the city uu.

Your task is to help Alex plan his city in a way that maximizes total score over all cities he visited. Note that for each city its score is counted at most once, even if Alex been there several times during his trip.

Input

First line of input contains two integers nn and mm, (1n21051≤n≤2⋅105, 0m21050≤m≤2⋅105) which are numbers of cities and roads in the country.

Second line contains nn integers w1,w2,,wnw1,w2,…,wn (0wi1090≤wi≤109) which are scores of all cities.

The following mm lines contain description of the roads. Each of these mm lines contains two integers uu and vv (1u,vn1≤u,v≤n) which are cities connected by this road.

It is guaranteed that there is at most one direct road between any two cities, no city is connected to itself by the road and, finally, it is possible to go from any city to any other one using only roads.

The last line contains single integer ss (1sn1≤s≤n), which is the number of the initial city.

Output

Output single integer which is the maximum possible sum of scores of visited cities.

Examples
input
Copy
5 7
2 2 8 6 9
1 2
1 3
2 4
3 2
4 5
2 5
1 5
2
output
Copy
27
input
Copy
10 12
1 7 1 9 3 3 6 30 1 10
1 2
1 3
3 5
5 7
2 3
5 4
6 9
4 6
3 7
6 8
9 4
9 10
6
output
Copy
61


解题报告:这个题目就是要求解最长的一个路径,让他在每条边只走一次的前提下,走过的点的权值之和最大。
利用vector存储好以后,使用dfs去爆搜就可以,这里有一个小的操作的优化,就是开设了一个s数组,用来存放
当前这个结点走到死胡同的路径上的点权值之和,剩下的暴力搜就可以。

ac代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
typedef long long ll;

const int maxn=2e5+100;
vector<int> edge[maxn];
ll w[maxn],s[maxn];
int mark[maxn],vis[maxn],pre[maxn];

void dfs(int v)
{
    vis[v]=1;
    for(int j=0;j<edge[v].size();j++)
    {
        int u=edge[v][j];
        if(vis[u])//如果u这个点走过,那么说明v是可到达的 
        {
            if(u!=pre[v])//如果v的父亲结点不是u的话,那么v不是死胡同的 
            {
                mark[v]=1;
            }
        }
        else//之前u这个点没有进行过访问 
        {
            pre[u]=v;//那么u的父亲结点就是v 
            dfs(u);//继续进行dfs以u为起点 
            if(mark[u]) mark[v]=1;//如果u在之后的搜索中是可以继续开拓的,就不是死胡同,那么v也是不是死胡同 
            else s[v]=max(s[u],s[v]);//如果u是没有办法继续开拓的,那么就是死胡同了 
        }
    }
    if(!mark[v])
        s[v]+=w[v];//如果是死胡同,那么死胡同路径上的全部点权加和 
    return;
}

int main()
{
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        cin>>w[i];    
    }    
    memset(s,0,sizeof(s));
    memset(mark,0,sizeof(mark));
    memset(vis,0,sizeof(vis));
    memset(pre,0,sizeof(pre));
    int u,v;
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&u,&v);
        edge[u].push_back(v);
        edge[v].push_back(u);
    }
    int st;
    scanf("%d",&st);
    dfs(st);
//    for(int i=1;i<=n;i++)
//    {
//        cout<<i<<" "<<s[i]<<endl;
//    }
    ll ans=0,maxx=0;
    for(int i=1;i<=n;i++)
    {
        if(mark[i])
            ans+=w[i];
        maxx=max(maxx,s[i]);
    }
    ans+=maxx;
    cout<<ans<<endl;
}


猜你喜欢

转载自www.cnblogs.com/Spring-Onion/p/11594902.html
今日推荐