还是要加强基本功啊。
多起点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;
}