CodeForces 506B/505D Mr. Kitayuta's Technology

Portal:http://codeforces.com/problemset/problem/506/B

    http://codeforces.com/problemset/problem/505/D 

好题

给n个城市,m条有向边,求出最少的有向边使得其构成的图与原图等势

对于每个连通分量:

如果无环,那么只需要需要n-1条边完成联通

如果有环,则只需要n条边完成联通

所以这题只要判下连通分量,再看有几个连通分量有环即可

解法一:无向图遍历求强连通分量再把强连通分量所代表的联通分量dfs判环,如下

Memory: 10440 KB   Time: 498 MS

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<set>
 4 #include<cstdio>
 5 #include<cstdlib>
 6 #include<cmath>
 7 #include<vector>
 8 using namespace std;
 9 #define FOR(i,j,k) for(int i=j;i<=k;i++)
10 #define FORD(i,j,k) for(int i=j;i>=k;i--)
11 #define LL long long
12 #define SZ(x) int(x.size())
13 #define maxn 100010
14 int n,m,x,y;
15 bool  circle=true;
16 int vis[maxn],vis2[maxn];
17 vector<int> neg[maxn],adj[maxn];
18 vector<int> dot;
19 void ndfs(int start)
20 {
21     dot.push_back(start);
22     vis[start]=1;
23     FOR(i,0,SZ(neg[start])-1)
24     {
25         if(!vis[neg[start][i]]) ndfs(neg[start][i]);
26
27     }
28     return;
29 }
30 void adfs(int start)
31 {
32     vis2[start]=1;
33     FOR(i,0,SZ(adj[start])-1)
34     {
35         if(!vis2[adj[start][i]]) adfs(adj[start][i]);
36         else if(vis2[adj[start][i]]==1)circle=false;
37     }
38     vis2[start]=2;
39     return;
40 }
41 int main()
42 {
43 cin>>n>>m;
44 FOR(i,1,m)
45 {
46     cin>>x>>y;
47     neg[x].push_back(y);
48     neg[y].push_back(x);
49     adj[x].push_back(y);
50 }
51 int ans=n;
52 FOR(i,1,n)
53 {
54     circle=1;
55     if(!vis[i])
56     {
57     dot.clear();
58     ndfs(i);
59     FOR(i,0,SZ(dot)-1)
60     if (!vis2[dot[i]]) adfs(dot[i]);
61     ans-=circle;
62     }
63 }
64 cout<<ans<<endl;
65 return 0;
66 }

我在想函数名字到底取afs好还是adfs好

解法二:在无向图中维护并查集求强连通分量再把强连通分量所代表的联通分量用拓扑排序判环,如下

Memory: 7820 KB   Time: 514 MS

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<set>
 4 #include<cstdio>
 5 #include<cstdlib>
 6 #include<cmath>
 7 #include<vector>
 8 using namespace std;
 9 #define FOR(i,j,k) for(int i=j;i<=k;i++)
10 #define FORD(i,j,k) for(int i=j;i>=k;i--)
11 #define LL long long
12 #define SZ(x) int(x.size())
13 #define maxn 100010
14 vector<int> G[maxn];
15 int n,m,x,y,T;
16 int father[maxn],val[maxn],circle[maxn],vis[maxn],clock[maxn];
17 int setfind(int x)
18 {
19     int fa=father[x];
20     if(fa==x) return x;
21     else return father[x]=setfind(fa);
22 }
23 void setunion(int x,int y)
24 {
25     int X=setfind(x);
26     int Y=setfind(y);
27     if(X==Y) return;
28     if(val[X]>val[Y]) father[Y]=X;
29     else father[X]=Y;
30     if(val[X]==val[Y]) val[X]++;
31     return;
32 }
33 void dfs(int start)
34 {
35     vis[start]=1;
36     FOR(i,0,SZ(G[start])-1)
37     if(!vis[G[start][i]]) dfs(G[start][i]);
38     clock[start]=++T;
39     return;
40 }
41 int main()
42 {
43 cin>>n>>m;
44 FOR(i,1,n)
45 {father[i]=i;val[i]=1;}
46 FOR(i,1,m)
47 {
48     cin>>x>>y;
49     G[x].push_back(y);
50     setunion(x,y);
51 }
52 FOR(i,1,n)
53 if(!vis[i]) dfs(i);
54 FOR(i,1,n)
55 FOR(j,0,SZ(G[i])-1)
56 if(clock[i]<clock[G[i][j]]) circle[setfind(i)]=1;
57 int ans=n;
58 FOR(i,1,n)
59 if(i==setfind(i))if(!circle[setfind(i)]) ans--;
60 cout<<ans<<endl;
61 return 0;
62 }

Mr. Kitayuta‘s Black Technology

其实求连通分量还可以用染色

  判有向环可以用并查集乱搞

反正就是怎么搞都能过

CodeForces 506B/505D Mr. Kitayuta's Technology

时间: 2024-11-07 23:33:48

CodeForces 506B/505D Mr. Kitayuta's Technology的相关文章

Codeforces Round #286 div.2 D 505D. Mr. Kitayuta&#39;s Technology【强连通分量,弱联通分量】

题目链接:http://codeforces.com/contest/505/problem/D 题目大意: 在一个图中,有n个顶点,给出m对数字(u,v)表示顶点u和顶点v必须直接或者间接相连,让你构造一个这样的图,输出最少需要多少条边. 分析: 毫无疑问,n个顶点的话,我们最多可以用n条边,使得n个顶点构成一个环,满足所有的情况(任意两点都是联通的),但是这并不一定是最少的边. 于是我们还需要找一个方法确定最少需要多少条边. 首先我们利用题目给出的点对建图,得到图G.对于G中的弱联通分量来说

codeforces 505 D Mr. Kitayuta&#39;s Technology

题意:给出n个点,m条有向边,问构造一个新图,最少几条边可以让任意两点间的连通性跟原图一样. 做法:首先做出强连通分量,很显然对于有向图而言,若分图的点不唯一必定成环,当然啦,还需要做的是把这些分图再连起来变成弱连通分量,若某个弱连通分量的点数为v,若有环则贡献v条边,否则贡献v-1条边. #include<map> #include<string> #include<cstring> #include<cstdio> #include<cstdlib

Codeforce 505D - Mr. Kitayuta&#39;s Technology 弱联通分量+拓扑排序

对于有向图M,若将其所有的边转化为无向边,则得到其基图M',若M'是联通的,则称有向图M是弱联通. 对于有向图M,若图中任意两点u,v(u != v)均满足u到v可达,v到u可达,则称此图为强联通. 根据以上定义显然可知,强联通图一定也满足弱联通. 此题首先我们需要找到其所有的弱联通分量. 对于每一个弱联通分量,设此弱联通分量内点的个数为ans,如果此联通分量无环,则需要的边数为ans-1,若有环则为ans. 太挫了,这种题都不会了,怎么变黄!!! #include <algorithm> #

【CF505D】Mr. Kitayuta&#39;s Technology

题目大意: 在一个有向图中,有n个顶点,给出m对数字(u,v)表示顶点u和顶点v必须直接或者间接相连,让你构造一个这样的图,输出最少需要多少条边. 挖坑待填 官方题解链接:http://codeforces.com/blog/entry/15889. 传送门:http://www.codeforces.com/problemset/problem/505/D [CF505D]Mr. Kitayuta's Technology

Codeforces 505 A Mr. Kitayuta&#39;s Gift【暴力】

题意:给出一个字符串,可以向该字符串的任意位置插入一个字母使其变成回文串 因为字符串的长度小于10,枚举插入的字母,和要插入的位置,再判断是否已经满足回文串 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include <cmath> 5 #include<stack> 6 #include<vector> 7 #include<map> 8

【Codeforces 506E】Mr.Kitayuta’s Gift&amp;&amp;【BZOJ 4214】黄昏下的礼物 dp转有限状态自动机+矩阵乘法优化

神题……胡乱讲述一下思维过程……首先,读懂题.然后,转化问题为构造一个长度为|T|+n的字符串,使其内含有T这个子序列.之后,想到一个简单的dp.由于是回文串,我们就增量构造半个回文串,设f(i,j,k)为构造到第i个位置,从前往后匹配到j,从后往前匹配到k,这样O(m*m*n)(没有观察到其转移的性质会再乘个26).再然后,发现不妙,在最后讨论奇偶.(我的思路到此为止……)接着,观察其转移的实质,发现其实dp的过程就是在一个有限状态自动机上行走,而有限状态自动机上的状态就是目前剩下的T,所以我

CodeForces 505B Mr. Kitayuta&#39;s Colorful Graph

Mr. Kitayuta's Colorful Graph Time Limit:1000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Submit Status Practice CodeForces 505B Description Mr. Kitayuta has just bought an undirected graph consisting of n vertices and m edges. The

codeforces 505A. Mr. Kitayuta&#39;s Gift 解题报告

题目链接:http://codeforces.com/problemset/problem/505/A 题目意思:给出一个长度不大于10的小写英文字符串 s,问是否能通过在字符串的某个位置插入一个字母,使得新得到的字符串成为回文串. /**************************************(又到自我反省时刻) 做的时候,通过添加一个单位使得长度增加1,找出中点,检验前一半的位置,找出对称位置替换成对应的前一半位置的字符,然后原字符串剩下的部分追加到后面,再判断回文.但是由于

codeforces Round 286# problem A. Mr. Kitayuta&#39;s Gift

Mr. Kitayuta has kindly given you a string s consisting of lowercase English letters. You are asked to insert exactly one lowercase English letter into s to make it a palindrome. A palindrome is a string that reads the same forward and backward. For