Description
Input
Output
Sample Input
3 3 3 1 2 2 3 3 1 3 3 1 2 2 3 1 3 6 6 1 2 2 3 3 1 4 5 5 6 6 4
Sample Output
Case 1: -1 Case 2: 1 Case 3: 15
为了防止做过的题就饭吃了,我这次要做完题就写博客==
题意:就是问加多少边依旧无环,无scc
做法:开始依旧想到了
其实只不过多了一个完全图而已,对于一个有n个节点的完全图而言,他有n*n个边,对于这个图而言,最终的结果必然是只有两个集合(即缩点之后的团)团内是scc无环,彼此之间只有单向的通道,设两个团的节点个数分别为x,y则最终可加的边数是n*n-n-x*y-m
in0 out0 是0还是1 要变一下!!
还有就是判-1,只用团的个数,最终结果可能等于0!
#include <iostream> #include<cstdio> #include<stack> #include<vector> #include<cstring> #include<algorithm> using namespace std; #define maxn 200005 vector<int>G[maxn]; int pre[maxn],lowlink[maxn],sccno[maxn],dfs_clock,scc_cnt; stack<int>S; int in0[maxn],out0[maxn]; void dfs(int u) { pre[u]=lowlink[u]=++dfs_clock; S.push(u);//<span style="font-family: Arial, Helvetica, sans-serif;">//每搜索到一个点,压入栈中</span> for(int i=0;i<G[u].size();i++)//遍历与p相连的点 { int v=G[u][i]; if(!pre[v])//不在栈中 { dfs(v); lowlink[u]=min(lowlink[u],lowlink[v]); } else if(!sccno[v])//在栈中 lowlink[u]=min(lowlink[u],pre[v]); } if(lowlink[u]==pre[u])//发现一个根 { scc_cnt++; for(;;) { int x=S.top();S.pop();//词典以上的所有点全部出栈 构成一个强连通分量 sccno[x]=scc_cnt;//scc_cnt是强连通分量的序号 if(x==u) break; } } } void find_scc(int n) { dfs_clock=scc_cnt=0; memset(sccno,0,sizeof(sccno)); memset(pre,0,sizeof(pre)); for(int i=0;i<n;i++) if(!pre[i]) dfs(i); } int num[100000]; int main() { // freopen("cin.txt","r",stdin); int T,n,m,cas=1; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); for(int i=0;i<n;i++) G[i].clear(); memset(num,0,sizeof(num)); for(int i=0;i<m;i++) { int u,v; scanf("%d%d",&u,&v); u--;v--; G[u].push_back(v); } find_scc(n); for(int i=1;i<=scc_cnt;i++) in0[i]=out0[i]=0; for(int u=0;u<n;u++) { for(int i=0;i<G[u].size();i++) { int v=G[u][i]; if(sccno[u]!=sccno[v]) in0[sccno[v]]=out0[sccno[u]]=1; } num[sccno[u]]++; } int maxnum=100000,maxtot; for(int i=1;i<=scc_cnt;i++) { //printf("i=%d,num=%d,in=%d,out=%d\n",i,num[i],in0[i],out0[i]); if(in0[i]==0||0==out0[i]) { if(num[i]<maxnum) { maxnum=num[i]; maxtot=i; } } } long long ans=n*n*1LL-n-1LL*maxnum*(n-maxnum)-m; if(scc_cnt!=1&&ans>=0) printf("Case %d: %lld\n",cas++,ans); else printf("Case %d: -1\n",cas++); } return 0; }