Codeforces Round #408 (Div. 2)-D. Police Stations-多起点bfs

还是要加强基本功啊。
多起点bfs,第一次接触。感觉挺好使。
又是勿入图论的阴霾,可能是我图论掌握的不好,一旦涉及见图的,我就开始想会不会是 scc啊,匹配啊什么的。因为我这方面掌握的不好,但是事实是bfs。。我是想到了,但是想的想当复杂,因为bfs是方便记录层数的(dinic算法上的),但是我没有想到多起点一起bfs,最重要的是不理解这道题的意思。
图中开始给定了就是满足条件的图,而只要求删除几条边,而删除边是不会增加距离的(其实是会的,但是我bfs的时候,因为是同时bfs,如果别人记录过了再删除,所以可以保证是较远的,不会增加距离,)。
用vis数组来表示是否被一个点 遍历,如果被了,我就可以删了他了。(因为重复嘛。毛子没钱嘛),然后光荣的记录他。
如果没有,我就暂且慢慢来。正常记录。
也可用一个队列来记录,这样就不会搞迷糊了。
http://codeforces.com/contest/796/problem/D

#include<bits/stdc++.h>
using namespace std;
/*多点bfs
我看了一眼,感觉差不多是bfs,但是应该挺麻烦的,不同的点bfs一次,还要记录他们的关系。
如果超过k了在删除,后来看了题解准备接受新的指示,
况且现在有点累了。。
一看题解竟然是bfs,。更令人崩溃的是k是没有用的,
代码思路是把所有的银行都给入队列,如果这个队列bfs到了另一个银行的点,
那么就可以把这个边删除了,
因为初始条件就可以满足,只是要知道有多少边就好了。
*/
const int maxn=300007;
struct Node
{   int to,i;
    Node(){};//不能没有空的队列。
    Node(int _a,int _b){to=_a;i=_b;};
}node[maxn];
queue<int>q;
vector<Node>G[maxn];
int edge[maxn];
bool vis[maxn];
int bfs()
{ int ans=0;
   while(!q.empty())
   {   int u=q.front();
        q.pop();
       for(int i=0;i<G[u].size();i++)
       {   Node s=G[u][i];
           if(edge[s.i]) continue;//已经访问过了。
           if(vis[s.to])
           {   edge[s.i]=2;
               //q.push(s.i);
               ans++;
               continue;//
           }
           vis[s.to]=true;
           edge[s.i]=1;
           q.push(s.to);

       }
   }
    return ans;
}
int main()
{   int m,n,k;
    int a,b;

    cin>>m>>n>>k;
     for(int i=1;i<=n;i++)
     {   scanf("%d",&k);
         vis[k]=true;
        q.push(k);
     }
    for(int i=1;i<m;i++)
    {  scanf("%d%d",&a,&b);
        G[a].push_back(Node(b,i));
        G[b].push_back(Node(a,i));

    }
    printf("%d\n",bfs());
    for(int i=1;i<m;i++)
    {   //printf("%d ",edge[i]);
        if(edge[i]==2)
        printf("%d ",i);

    }
    printf("\n");
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值