D. D/D/D

题目链接:https://codeforces.com/contest/2109/problem/D

题意:

给定一个无向图,以及一个集合

现在要求从点1走到点i

操作任意次。每次可以从集合中取任意一个数,然后删除。并将其大小k作为这次走的路的长度k(恰好经过k个边,可以来回走)

每个i点的查询都是相互独立的(不改变题目给的集合)

思路:

发现从1走到一个点经过的边数为m,m有奇偶性,然后能走到其相邻点再走回来长度为m+2

注意到2是偶数不改变m的奇偶性

根据题目给的样例,发现图可以有,此时其他点有机会得到具有不同的奇偶性长度的路径

因此,分析得到我们需要 到达每个点的奇偶路径的最短长度

再贪心地取得题目给定集合中能走的最长的奇偶路径

那么分别判断能走的最长奇偶路径长度是否大于等于该点的最短奇偶路径长度(大于时,至少大2),取或

求到达每个点的奇偶路径需要使用BFS,以dj的思想求最短路

vector<int>e[maxn];
int dis[maxn][2];
void bfs(){
    queue<pii>q;
    q.push({1,0});
    while(q.size()){
        pii now=q.front();q.pop();
        int u=now.fi,c=now.se;
        for(int v:e[u]){
            if(dis[v][1-c]==-1){
                dis[v][1-c]=dis[u][c]+1;
                q.push({v,1-c});
            }
        }
    }
}
void solve(){
    int n,m,l;cin>>n>>m>>l;
    memset(dis,-1,sizeof dis);
    dis[1][0]=0;
    rep(i,1,n){
        e[i].clear();
    }
    vector<int>a(l+1);
    int sum=0;
    rep(i,1,l){
        cin>>a[i];
        sum+=a[i];
    }
    int emax=0,omax=0;
    if(sum&1)omax=sum;else emax=sum;
    for(int i=1;i<=l;i++){
        int x=sum-a[i];
        // debug(x);
        if(x&1){
            omax=max(omax,x);
        }else emax=max(emax,x);
    }
    rep(i,1,m){
        int u,v;cin>>u>>v;
        e[u].pb(v);e[v].pb(u);
    }
    bfs();

    for(int i=1;i<=n;i++){
        if(dis[i][0]!=-1){
            if(emax>=dis[i][0]){
                cout<<1;continue;
            }
        }
        if(dis[i][1]!=-1){
            if(omax>=dis[i][1]){
                cout<<1;continue;
            }
        }
        cout<<0;
    }
    cout<<endl;
}
posted @ 2025-05-20 22:27  Marinaco  阅读(19)  评论(0)    收藏  举报
//雪花飘落效果