列表

详情


NC14411. 团结就是力量

描述

从小老师就教育我们,一根筷子容易折断,而一捆筷子不容易折断。
因为要出战世界杯,我们需要考虑派一只队伍出战,而我们希望出战的队伍的团结力最大。
而一个队伍的团结力取决于每个人的性格,每个人都有一个性格基因【(由字符串表示),比如小明的性格基因为:abbcde】,性格基因的排列方式是可以通过一个人的后天培养而改变的,其改变方式就是类似于循环,【小明的性格基因为:abbcde,他可以变成:bbcdea,bcdeab,cdeabb,deabbc,eabbcd】 。
一个队伍中如果最多有x个人的性格基因可以完全相等的话,那么这个队伍的团结力就是x。
比如一个队伍有五个人:
小明:abbcde
小红:bbcdea
大明:cdeabb
大红:efg 
小紫:fge
明显小明小红和大明的性格基因可以变成相等的,大红和小紫的性格基因可以变成相等的, 这个最多有3个人的性格基因可以完全相等的,所以这个五人队伍的团结力就是3;

现在已知可以出战的人数为n个,每个人都有一个性格基因字符串,而作为一只队伍出战的话,需要队伍中的每个人都互相达成共识。同时也已知m个信息,每个信息是:
a想要和b一起出战【注意,这里只是a的一厢情愿】,只有当a想要和b一起出战,并且b也想要和a一起出战的时候,两个人才能一起出战。想要一起出战是可以具有传递性的,比如a想要和b一起出战,b想要和c一起出战的话,那么a也可以想要和c一起出战。

我们肯定希望派出的队伍的团结力最大,请计算出这个最大团结力。  

输入描述

本题包含多组数据,第一行输入两个数字n,m,分别表示一共有n个人,以及m个出战信息 。
接下来n行,每行输入一个字符串,表示每个人的性格基因。
再接下来m行,每行两个编号x,y,表示x想要和y出战
数据范围:
5<=n<=100000
1<=m<=100000
1<=x,y<=n
每个数据的字符串长度和不超过100000

输出描述

每组数据输出一行,表示最大团结力。

示例1

输入:

5 5
abbcde
bbcdea
cdeabb
efg
fge
1 2
2 3
3 4
4 5
5 1
6 7
abbcde
bbcdea
cdeabb
efg
fge
gef
1 2
2 3
3 1
4 5
5 6
6 4
2 4

输出:

3
3

说明:

第一个样例题干中有所描述。这里1想和2出战,2想和3出战,3想和4出战,4想和5出战,5又想和1出战,那么就相当于每个人都想要互相一起出战,所以这就是一个队伍。
第二个样例中,123号三个人是一个队伍,456号是一个队伍,虽然2想和4一起出战,但是已知m条信息中,不能构成4想和2出战的信息出来,所以六个人不能变成一个队伍。

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 828ms, 内存消耗: 133672K, 提交时间: 2020-05-14 16:55:24

//
// Created by ZHY on 2020/5/12.
//
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int mod=19260817;
const int MX=2001000;

ll n,m,cnt,sum;
int ans=0;
vector<int>ve[MX];
int dfn[MX],low[MX];
bool vis[MX];
stack<int>st;
string s[MX];
map<string,int>mp;

void tarjan(int x){
    dfn[x]=low[x]=++cnt;
    st.push(x);vis[x]=1;
    for(int i:ve[x]){
        if(!dfn[i]){
            tarjan(i);
            low[x]=min(low[i],low[x]);
        }else if(vis[i]){
            low[x]=min(dfn[i],low[x]);
        }
    }
    if(low[x]==dfn[x] ){
        int xx,k;sum++;
        mp.clear();
        do{
            k=st.top();st.pop();
            xx=++mp[s[k]];
            vis[k]=0;
            ans=max(xx,ans);
        }while(k!=x);
    }

}

int main()
{
    while(cin>>n>>m) {
        for (int i = 1; i <= n; i++)
        {
            ve[i].clear();vis[i]=0;
            dfn[i]=low[i]=0;
        }
        while(!st.empty()){
            st.pop();
        }
        ans=0;
        for(int i=1;i<=n;i++)
        {
            cin>>s[i];
            sort(s[i].begin(),s[i].end());
        }
        for(int i=0,x,y;i<m;i++)
        {
            cin>>x>>y;
            ve[x].push_back(y);
        }
        for(int i=1;i<=n;i++)
        {
            if(!dfn[i]){
                tarjan(i);
            }
        }
        cout<<ans<<"\n";
    }
    return 0;
}

C++(g++ 7.5.0) 解法, 执行用时: 377ms, 内存消耗: 20312K, 提交时间: 2023-05-10 18:47:48

#include<bits/stdc++.h>
using namespace std;
int n,m;
const int N = 1e5+10;
int h[N],ne[N],e[N];
int s[N],top,tot,ans;
int dfn[N];
int scc_cnt,idx;
int low[N];
int ins[N];
map<string,int> mp;
void add(int a,int b)
{
	e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
string v[N];
void tarjan(int u)
{
	dfn[u]=++tot;
	ins[u]=true;
	low[u]=tot;
	s[++top]=u;
	for(int i=h[u];~i;i=ne[i])
	{
		int j=e[i];
		if(!dfn[j])
		{
			tarjan(j);
			low[u]=min(low[u],low[j]);
		}
		else if(ins[j]) low[u]=min(low[u],dfn[j]); 
	}
	if(low[u]==dfn[u])
	{
		scc_cnt++;
		mp.clear();
		while(1)
		{
			int x=s[top--];
			ins[x]=false;
			mp[v[x]]++;
			if(u==x) break;
		}
		for(auto i:mp) ans=max(ans,i.second);
	}
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	while(cin>>n>>m)
	{
		memset(h,-1,sizeof h);
		idx=0,top=0,scc_cnt=0;
		memset(low,0,sizeof low);
		memset(dfn,0,sizeof dfn);
		for(int i=1;i<=n;i++)
		{
			string t;
			cin>>t;
			sort(t.begin(),t.end());
			v[i]=t;
		}
		for(int i=1;i<=m;i++)
		{
			int a,b;
			cin>>a>>b;
			add(a,b);
		}
		ans=0;
		for(int i=1;i<=n;i++) 
		{
			if(!dfn[i])
			{
				tarjan(i);
			}
		}
		cout<<ans<<endl;
	}
}

C++ 解法, 执行用时: 331ms, 内存消耗: 10716K, 提交时间: 2022-01-11 15:44:09

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;

int h[N],e[N],ne[N],idx;
int dfn[N],low[N],timestamp;
int stk[N],top,ans;
string s[N];
char ss[N];
bool in_stk[N];
map<string,int>mp;

void init()
{
	memset(h,-1,sizeof h);
	idx=timestamp=ans=0;
	memset(dfn,0,sizeof dfn);
	memset(low,0,sizeof low);
}

void add(int a,int b)
{
	e[idx]=b;
	ne[idx]=h[a];
	h[a]=idx++;
}

void tarjan(int u)
{
	dfn[u]=low[u]=++timestamp;
	stk[top++]=u,in_stk[u]=1;
	for(int i=h[u]; ~i; i=ne[i])
	{
		int v=e[i];
		if(!dfn[v])
		{
			tarjan(v);
			low[u]=min(low[u],low[v]);
		}
		else if(in_stk[v])
		{
			low[u]=min(low[u],dfn[v]);
		}
	}
	if(dfn[u]==low[u])
	{
		int y;
		do
		{
			y=stk[--top];
			in_stk[y]=0;
			mp[s[y]]++;
			ans=max(ans,mp[s[y]]);
		}
		while(y!=u);
		mp.clear();
	}
}

int main()
{

	int n,m;
	while(~scanf("%d%d",&n,&m))
	{
		init();
		for(int i=1; i<=n; i++)
		{
			scanf("%s",ss+1);
			int len=strlen(ss+1);
			sort(ss+1,ss+len+1);
			s[i]=(ss+1);
		}
		for(int i=1; i<=m; i++)
		{
			int x,y;
			scanf("%d%d",&x,&y);
			add(x,y);
		}
		for(int i=1; i<=n; i++)
		{
			if(!dfn[i])tarjan(i);
		}
		printf("%d\n",ans);
	}
}

上一题