Each input file contains one test case. Each case starts with a line containing 3 numbers N (<1000), M and K, which are the total number of cities, the number of remaining highways, and the number of cities to be checked, respectively. Then M lines follow, each describes a highway by 2 integers, which are the numbers of the cities the highway connects. The cities are numbered from 1 to N. Finally there is a line containing K numbers, which represent the cities we concern.
For each of the K cities, output in a line the number of highways need to be repaired if that city is lost.
3 2 3<br/>1 2<br/>1 3<br/>1 2 3
1<br/>0<br/>0
package go.jacob.day830; import java.util.Scanner; /** * 1013. Battle Over Cities (25) * * @author Jacob 运用连通集。 * 连通集具体数据结构参考:http://blog.csdn.net/zjkc050818/article/details/77703880 * 这里使用quick_union */ public class Demo2 { static int count;// 记录连通集个数 private static int[] id;// 记录每个节点属于哪个集合 private static int[] size;// 记录每个集合的节点个数,当将两个集合连通时,将节点数较少的集合加到节点数较多的集合上 public static void main(String[] args) { Scanner sc = new Scanner(System.in); int citys = sc.nextInt(), roads = sc.nextInt(), checked = sc.nextInt(); if(citys<2){ System.out.println(0); return; } // 由于节点序号是从1开始,所以初始化的时候要注意 id = new int[citys + 1]; size = new int[citys + 1]; // 保存所有路径 int[][] road = new int[roads][2]; for (int i = 0; i < roads; i++) { road[i][0] = sc.nextInt(); road[i][1] = sc.nextInt(); } int[] checkCity = new int[checked]; for (int i = 0; i < checked; i++) checkCity[i] = sc.nextInt(); for (int i = 0; i < checked; i++) { init(); solve(checkCity[i], road); } sc.close(); } // 初始化id和size数组.每个节点属于本节点,且个数为1 private static void init() { for (int i = 1; i < id.length; i++) { id[i] = i; size[i] = 1; } count = id.length-1; } private static void solve(int root, int[][] road) { for (int i = 0; i < road.length; i++) { int p = road[i][0], q = road[i][1]; // 如果本条路径中有root节点,则跳过此次循环。 if (p == root || q == root) continue; union(p,q); } //count()返回连通集个数,-2的原因是: //删除某一个节点需要减1,删除以后,如果有N个连通集,相连需要N-1条边 System.out.println(count()-2); } /* * 查找p属于的连通集 */ private static int find(int p) { while(id[p]!=p) p=id[p]; return p; } /* * 将p,q所在的两个连通集相连 */ private static void union(int p, int q) { int pRoot=find(p),qRoot=find(q); if(pRoot==qRoot) return; if(size[pRoot]>size[qRoot]){ id[qRoot]=pRoot; size[pRoot]+=size[qRoot]; }else{ id[pRoot]=qRoot; size[qRoot]+=size[pRoot]; } count--; } /* * 返回连通集数 */ private static int count() { return count; } }
//Dfs实现联通块的计算
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
const int maxn = 1000 + 10;
int current_point, vis[maxn];
vector<int> G[maxn];
void dfs(int p){
if(p == current_point) return;
if(vis[p]) return;
vis[p] = 1;
for(unsigned int i=0;i<G[p].size();i++){
dfs(G[p][i]);
}
}
int main(){
int n, m, k;
scanf("%d %d %d", &n, &m, &k);
for(int i=0;i<m;i++){
int p1, p2;
scanf("%d %d", &p1, &p2);
G[p1].push_back(p2);
G[p2].push_back(p1);
}
for(int i=0;i<k;i++){
int block=0;
scanf("%d", ¤t_point);
memset(vis, 0, sizeof(vis));
for(int j=1;j<=n;j++){
if(!vis[j]){
dfs(j);
block ++;
}
}
printf("%d\n", block-2);
}
if(n && !m && k)
printf("0\n");
return 0;
} //并查集实现较为简单且高效
#include <set>
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int maxn = 1000 + 10;
struct Edge
{
int p1, p2;
Edge(int u, int v):p1(u), p2(v) {}
};
set<int> block;
vector<Edge> edges;
int p[maxn];
int find_sym(int x){
return (p[x] == x)? x : (p[x] = find_sym(p[x]));
}
int main(){
int n, m, k;
scanf("%d %d %d", &n, &m, &k);
for(int i=0;i<m;i++){
int u, v;
scanf("%d %d", &u, &v);
edges.push_back(Edge(u, v));
}
for(int i=0;i<k;i++){
int lost_city;
scanf("%d", &lost_city);
block.clear();
memset(p, 0, sizeof(p));
for(int j=1;j<=n;j++) p[j] = j;
for(int h=0;h<m;h++){
Edge e = edges[h];
if(e.p1==lost_city || e.p2==lost_city) continue;
else{
int x = find_sym(e.p1);
int y = find_sym(e.p2);
if(x!=y) p[x] = y;
}
}
for(int j=1;j<=n;j++){
int symbol = find_sym(j);
if(!block.count(symbol)) block.insert(symbol);
}
cout << block.size()-2 << endl;
}
return 0;
} #include <iostream>
#include <algorithm>
using namespace std;
const int maxn=1010;
int n,m,k,ans,v1,v2;
int G[maxn][maxn];
bool vis[maxn]={false};
void DFS(int u){
vis[u]=true;
for(int v=1;v<=n;v++){
if(vis[v]==false&&G[u][v]==1)
DFS(v);
}
}
void DFSTrave(){
for(int u=1;u<=n;u++){
if(vis[u]==false){
DFS(u);
ans++;
}
}
}
int main(){
cin>>n>>m>>k;
for(int i=1;i<=m;i++){
scanf("%d%d",&v1,&v2);
G[v1][v2]=G[v2][v1]=1;
}
for(int i=1;i<=k;i++){
fill(vis,vis+1010,false); //初始化访问结点
cin>>v1;
vis[v1]=true; //本轮绕过v1
ans=0;
DFSTrave();
if(n==1) cout<<0<<"\n"; //特例,只有一个点时
else cout<<ans-1<<"\n"; //要添加的边数即为连通分量数减1
}
return 0;
} #include<iostream>
#include<string>
#include<vector>
using namespace std;
struct Edge
{
int nextIndex;//下一个结点的id
bool isUsed;//是否损毁
};
void dfs(vector<Edge> roadMaps[1001],int N,int nextRoadId,bool *usedCity)
{
usedCity[nextRoadId] = true;
for(int i=0;i<roadMaps[nextRoadId].size();i++)
{
int nextId = roadMaps[nextRoadId][i].nextIndex;
if(!usedCity[nextId]&&roadMaps[nextRoadId][i].isUsed)
dfs(roadMaps,N,nextId,usedCity);
}
};
void checkThisNode(vector<Edge> roadMaps[1001],int checkCityId,int N)
{
int realId = checkCityId-1;
//cout<<"check:"<<checkCityId<<endl;
for(int i=0;i<roadMaps[realId].size();i++)
{
roadMaps[realId][i].isUsed = false;//设置成被损毁的路
}
bool usedCity[1001]={false};
//找到孤立的结点,然后遍历
int sum = 0;
for(int i=0;i<N;i++)
{
if(i==realId)
continue;
if(!usedCity[i])
sum++;
dfs(roadMaps,N,i,usedCity);
}
cout<<sum-1<<endl;
for(int i=0;i<roadMaps[realId].size();i++)
{
roadMaps[realId][i].isUsed = true;//恢复被损毁的路
}
};
int main()
{
int N,M,K;
scanf("%d %d %d",&N,&M,&K);
vector<Edge> roadMaps[1001];
for(int i=0;i<M;i++)
{
int a,b;
scanf("%d %d",&a,&b);
Edge tmp;
tmp.nextIndex = b-1;
tmp.isUsed = true;
roadMaps[a-1].push_back(tmp);
Edge tmp2;
tmp2.nextIndex = a-1;
tmp2.isUsed = true;
roadMaps[b-1].push_back(tmp2);
//cout<<"a="<<a<<" b="<<b<<endl;
}
//cout<<"id:"<<roadMaps[0][2].nextIndex<<endl;
for(int i=0;i<K;i++)
{
int needCheck;
scanf("%d",&needCheck);
checkThisNode(roadMaps,needCheck,N);
}
return 0;
}
#include<bits/stdc++.h>
using namespace std;
const int Max=1010;
vector<int> G[Max];
bool visit[Max];
int query;
void DFS(int v) {
visit[v]=1;
for(int i=0; i<G[v].size(); i++) {
if(!visit[G[v][i]]&&G[v][i]!=query) {
DFS(G[v][i]);
}
}
}
int main() {
int n,m,k;
scanf("%d %d %d",&n,&m,&k);
for(int i=0; i<m; i++) {
int x,y;
scanf("%d %d",&x,&y);
G[x].emplace_back(y);
G[y].emplace_back(x);
}
for(int q=0; q<k; q++) {
scanf("%d",&query);
int answer=-1;
memset(visit,0,sizeof(visit));
for(int i=1; i<=n; i++) {
if(query==i||visit[i]) continue;
DFS(i);
answer++;
}
if(answer==-1) printf("0");
else printf("%d\n",answer);
}
return 0;
} #include<cstdio>
(802)#include<algorithm>
using namespace std;
const int maxn=1010;
const int INF=0x3fffffff;
int G[maxn][maxn]={0},graph[maxn][maxn];
bool vis[maxn];
void DFS(int start,int n)
{
vis[start]=true;
for(int i=1;i<=n;i++)
{
if(vis[i]==false&&graph[start][i]==1)
DFS(i,n);
}
}
int main()
{
int n,m,k;
scanf("%d%d%d",&n,&m,&k);
if(n==1)
{
puts("0");
return 0;
}
for(int i=0;i<m;i++)
{
int c1,c2;
scanf("%d%d",&c1,&c2);
G[c1][c2]=1;
G[c2][c1]=1;
}
for(int i=0;i<k;i++)
{
fill(vis,vis+maxn,false);
int c=0,num=0;
for(int j=1;j<=n;j++)
for(int m=1;m<=n;m++)
graph[j][m]=G[j][m];
scanf("%d",&c);
for(int j=1;j<=n;j++)
if(graph[c][j]==1)
{
graph[c][j]=0;
graph[j][c]=0;
}
for(int j=1;j<=n;j++)
if(vis[j]==false)
{
num++;
DFS(j,n);
}
printf("%d\n",num-2);
}
return 0;
} #include<bits/stdc++.h>
using namespace std;
int G[1005][1005] ={0};
int vis[1005];
void dfs(int i ,int n) {
vis[i] = 1;
for (int j = 1; j < n+1; j++) {
if (vis[j] == 0 && G[i][j] == 1) {
dfs(j, n);
}
}
}
int main() {
int n, m, k;
cin >> n >> m >> k;
while (m--) {
int a, b;
scanf("%d %d",&a,&b);
G[a][b] = 1;
G[b][a] = 1;
}
int city;
while (cin >> city) {
fill(vis,vis+1005,0);
vis[city] = 1;
int cnt = 0;
for (int i = 1; i < n+1; i++) {
if (vis[i] == 0){
dfs(i, n+1);
cnt++;
}
}
printf("%d\n",max(0,cnt-1));
}
} #使用并查集
#include<iostream>
using namespace std;
int Tree[1000];
int key[1000];
struct Edge{
int x, y;
}edges[1000000];
int findRoot(int x){
if(Tree[x] == -1) return x;
else{
int temp = findRoot(Tree[x]);
Tree[x] = temp;
return temp;
}
}
void combine(int a, int b){
int r_a = findRoot(a);
int r_b = findRoot(b);
if(r_a != r_b) Tree[r_a] = r_b;
}
int main(){
int N,M,K;
cin>>N>>M>>K;
for(int i = 0; i < M; i++){
int a, b;
cin>>a>>b;
edges[i].x = a;
edges[i].y = b;
}
for(int i = 0; i < K; i++){
cin>>key[i];
}
for(int i = 0; i < K; i++){
int k = key[i],counter=0;
fill(Tree,Tree+N+1,-1);
for(int j = 0; j < M; j++){
if(edges[j].x != k && edges[j].y !=k){
combine(edges[j].x, edges[j].y);
}
}
for(int j = 1; j < N+1; j++)
if(Tree[j]==-1) counter++;
cout<<((counter-2)>0?counter-2:0)<<endl;
}
return 0;
} #include <iostream>
using namespace std;
int main() {
int i, j, x, y;
int n, m, k;
int c1, c2;
int count;
bool map[1000][1000] = {0};
scanf("%d %d %d", &n, &m, &k);
for (i = 0; i < m; ++i) {
scanf("%d %d", &c1, &c2);
map[c1][c2] = true;
map[c2][c1] = true;
}
for (i = 0; i < k; ++i) {
scanf("%d", &c1);
count = 0;
for (x = 1; x <= n; ++x) {
if (x == c1) {
continue;
}
for (y = x+1; y <= n; ++y) {
if (y == c1) {
continue;
}
if (map[x][y]) {
++count;
}
}
}
count = (n - 2) - count;
count = count >= 0 ? count : 0;
printf("%d\n", count);
}
return 0;
}
#include<algorithm>
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn=1010;
vector<int> G[maxn];
int N,M,K;
int delP;
bool vis[maxn]={0};
void DFS(int x)
{
vis[x]=1;
for(int i=0;i<G[x].size();i++)
{
if(vis[G[x][i]]==0 && delP!=G[x][i] )
{
DFS(G[x][i]);
}
}
}
int main()
{
cin>>N>>M>>K;
//类似于链表
for(int i=0;i<M;i++)
{
int c1,c2;
cin>>c1>>c2;
G[c1].push_back(c2);
G[c2].push_back(c1);
}
for(int del=0;del<K;del++)
{
memset(vis,0,sizeof(vis));
cin>>delP;
int block=0;
for(int i=1;i<=N;i++)
if(vis[i]==false && i!=delP)
{
DFS(i);
block++;
}
if(block==0) cout<<block<<endl;
else cout<<block-1<<endl;
}
} 就dfs了一下求连通集数量
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
//邻接矩阵
int connect_matrix[1005][1005] = { 0 };
vector<int> result;
bool mark[1005] = { false };
void dfs(int lost, int total, int pos)
{
mark[pos] = true;
for (int i = 1; i <= total; i++) {
if (mark[i] == false && connect_matrix[pos][i] == 1
&& i != lost) {
dfs(lost, total, i);
}
}
}
int main()
{
int M, N, K;
cin >> M >> N >> K;
int start, end;
for (int i = 0; i < N; i++) {
cin >> start >> end;
connect_matrix[start][end] = 1;
connect_matrix[end][start] = 1;
}
int occupied;
int road = 0;
for (int i = 0; i < K; i++) {
cin >> occupied;
memset(mark, false, 1005);
road = 0;
for (int j = 1; j <= M; j++) {
if (mark[j] == false && j != occupied) {
dfs(occupied, M, j);
road++;
}
}
result.push_back(road==0?road:road-1);
}
for (int i = 0; i < result.size(); i++)
cout << result[i] << endl;
return 0;
}
}
{
if (JH[num]==-1) return num;
else
{
int temp= findroot (JH[num],JH);
JH[num]=temp;
return temp;
}
}
#include <iostream>
#include <stdio.h>
int edge[2][10000];
int main( int argc, const char * argv[]) {
int n,m,k;
scanf ( "%d %d %d" ,&n,&m,&k);
int i;
for (i=0;i<m;i++)
{
int a,b;
scanf ( "%d %d" ,&a,&b);
edge [0][i]=a;
edge [1][i]=b;
}
for (i=0;i<k;i++)
{
int city,count=0;
scanf ( "%d" ,&city);
int JH[1001];
int j;
for (j=1;j<=n ;j++)
JH[j]=-1;
for (j=0;j<m;j++)
{
if ( edge [0][j]!=city&& edge [1][j]!=city)
{
int root1= findroot ( edge [0][j],JH);
int root2= findroot ( edge [1][j],JH);
if (root1!=root2)
{
JH[root2]=root1;
}
}
}
JH[city]=0;
for (j=1;j<=n;j++)
{
if (JH[j]==-1)
count++;
}
if (n!=1)
printf ( "%d\n" ,count-1);
else
printf ( "0\n" );
}
return 0;
}
import java.util.Scanner;
public class test1013_2 {
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
while(scanner.hasNext()){
int citys=scanner.nextInt();
if(citys==1) {
System.out.println(0);
return;
}
int roads=scanner.nextInt();
MAX=citys+1;
father =new int[MAX];
rank=new int[MAX];
int checked=scanner.nextInt();
int[][] road=new int[roads][2];
for (int i = 0; i < road.length; i++) {
road[i][0]=scanner.nextInt();
road[i][1]=scanner.nextInt();
}
int[] check=new int[checked];
for (int i = 0; i < checked; i++) {
check[i]=scanner.nextInt();
}
cal(citys,road,check);
}
}
private static void cal(int citys, int[][] road, int[] check) {
int res[]=new int[check.length];
for (int i = 0; i < check.length; i++) {
int temp=check[i];
res[i]=citys-2-helper(temp,road,citys);
}
for (int i = 0; i < res.length; i++) {
System.out.println(res[i]);
}
}
private static int helper(int temp, int[][] road, int citys) {
int res=0;
init();//初始化高度和父节点
for (int i = 0; i < road.length; i++) {
int a=road[i][0];
int b=road[i][1];
if(a==temp||b==temp) continue;//删除和temp有关的边
if(Union(a, b)) res++;
}
return res;
}
// 初始化秩(树的高度)和父节点
private static void init() {
for (int i = 0; i <father.length; i++) {
father[i]=i;
}
for (int i = 0; i < rank.length; i++) {
rank[i]=1;
}
}
static int MAX;
static int father[]; /* father[x]表示x的父节点*/
static int rank[]; /*rank[x]表示x的秩*/
static int find(int x){
if(father[x]!=x){
father[x]=find(father[x]);//这个回溯时的压缩路径是精华
}
return father[x];
}
//判断是否Union成功
static boolean Union(int x,int y){
x=find(x);
y=find(y);
if(x==y) return false;
else {
if(rank[x]>rank[y])
father[y]=x;
else{
if(rank[x]==rank[y]) rank[y]++;
father[x]=y;
}
}
return true;
}
}
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
const int maxn=1005;
int n,m,k;
bool vis[maxn];
vector<int>v[maxn];
void dfs(int u){
vis[u]=true;
for(int i=0;i<v[u].size();i++){
if(!vis[v[u][i]]){
dfs(v[u][i]);
}
}
}
int main(){
//freopen("in.txt","r",stdin);
scanf("%d%d%d",&n,&m,&k);
int from,to,u,ans;
for(int i=0;i<m;i++){
scanf("%d%d",&from,&to);
v[from].push_back(to);
v[to].push_back(from);
}
for(int i=0;i<k;i++){
fill(vis,vis+n+1,false);
ans=-1;
scanf("%d",&u);
vis[u]=true;
for(int i=1;i<=n;i++){
if(!vis[i]){
dfs(i);
ans++;
}
}
ans=max(ans,0);
printf("%d\n",ans);
}
return 0;
}
#include<cstdio>
#include<cstring>
#include<vector>
#define maxn 1010
using namespace std;
vector<int>g[maxn];
bool visit[maxn];
int map[1000][1000]={0};
int n,k,m,a;
int concern[1000];
void dfs(int i){
if(i==a)return;
if(visit[i]==1)return;
visit[i]=1;
for(int j=0;j<g[i].size();j++){
dfs(g[i][j]);
}
}
int main(){
scanf("%d%d%d",&n,&m,&k);
for(int i=0;i<m;i++){
int x,y;
scanf("%d%d",&x,&y);
g[x].push_back(y);
g[y].push_back(x);
}
for(int i=0;i<k;i++){
scanf("%d",&a);
memset(visit,0,sizeof(visit));
int block=0;
for(int j=1;j<=n;j++){
if(visit[j]==0){
block++;
dfs(j);
}
}
printf("%d\n",block-2);
}
return 0;
}
bfs搜索并计数联通集的个数,用vector存储图