http://acm.hdu.edu.cn/showproblem.php?pid=6795
给定n个点,有两种点,权值分别为1和2,
初始时,n个点互不相连。初始时,n个点互不相连。初始时,n个点互不相连。
接着会加入n−1条边,保证每次加入的边的两个端点事先是不相连通的。
要从中选择3个点,满足3个点的权值之和不少于5,且3个点之间互不相连,计算出不同的选择方案的数量。
每加入一条边,都要输出当前连通状态下,不同的选择方案的数量。
初始状态的计算:假设权值为1的点的数量为cnt1,权值为2的点的数量为cnt2,
此时的不同方案的总数:
ans = C2cnt2 x C1cnt1 + C3cnt2
我们考虑每次添加一条边后,会有哪一部分的方案会变成不合法的方案
由于每次加边合并都是对两个连通块进行操作,假设现在u和v之间添加一条边
因此,我们将n个点分为3个部分:u所在连通块Gu、v所在的连通块Gv、其他剩余点Gr。
不合法的方案有以下四种:
(1)Gu选择一个权值为1的点,Gv选择一个权值为2的点,Gr选择一个权值为2的点。
(2)Gu选择一个权值为2的点,Gv选择一个权值为1的点,Gr选择一个权值为2的点。
(3)Gu选择一个权值为2的点,Gv选择一个权值为2的点,Gr选择一个权值为2的点。
(4)Gu选择一个权值为2的点,Gv选择一个权值为2的点,Gr选择一个权值为1的点。
参考博客:https://blog.csdn.net/njuptACMcxk/article/details/107641773
#include
#include
#include
#include
#include
#define ll long long
using namespace std;
const int N=1e5+10, mod=1e9+7;
int T,n;
int w[N];
int cnt[3];
int p[N];
int p1[N],p2[N];
int Find(int x)
{
if(p[x]!=x) p[x]=Find(p[x]);
return p[x];
}
int C_2(int n)
{
if(n<2) return 0;
return (ll)(n-1)*n/2%mod;
}
int C_3(int n)
{
if(n<3) return 0;
return (ll)(n)*(n-1)*(n-2)/6%mod;
}
int main()
{
cin>>T;
while(T--)
{
scanf("%d",&n);
memset(cnt,0,sizeof cnt);
for(int i=1;i<=n;i++)
{
scanf("%d",&w[i]);p[i]=i;
if(w[i]==1) {p1[i]=1, p2[i]=0;cnt[1]++;}
else {p2[i]=1, p1[i]=0;cnt[2]++;}
}
int ans=(C_3(cnt[2])+(ll)C_2(cnt[2])*cnt[1]%mod)%mod;
printf("%d\n",ans);
int u,v;
for(int i=0;i<n-1;i++)
{
int k=0;
scanf("%d%d",&u,&v);
int pu=Find(u), pv=Find(v);
k=(k+(ll)p1[pu]*p2[pv]*(cnt[2]-p2[pu]-p2[pv]))%mod;
k=(k+(ll)p2[pu]*p1[pv]*(cnt[2]-p2[pu]-p2[pv]))%mod;
k=(k+(ll)p2[pu]*p2[pv]*(cnt[2]-p2[pu]-p2[pv]))%mod;
k=(k+(ll)p2[pu]*p2[pv]*(cnt[1]-p1[pu]-p1[pv]))%mod;
ans=(ans-k+mod)%mod;
printf("%d\n",ans);
p[pv]=pu;
p1[pu]+=p1[pv], p2[pu]+=p2[pv];
p1[pv]=0, p2[pv]=0;
}
}
return 0;
}
http://acm.hdu.edu.cn/showproblem.php?pid=6799
给字符串s,s含有:( ) * 三种字符。你可以将 * 转化成左右括号,或者不转换。s求符合括号匹配的情况下,最小的字典序并输出。没有答案输出"No solution!"
优先从左边把星星改为左括号,完成右括号的匹配。
在把从右边把星星改为右括号,完成左括号的匹配。
这样字典序就保证最小了。
#include
#include
#include
#include
#include
#include
#define inf 2147483647
using namespace std;
typedef long long ll;
const int maxn = 100005;
char s[maxn];
int l[maxn],r[maxn],local[maxn];
int main()
{
// freopen("1009.txt", "r", stdin); // ¶áèë¸ÕD′μÄÎļt
// freopen("1009zhz.out", "w", stdout); // êä3ö½«òaêä3öμÄêy¾Y
int T;
int cnt=1;
scanf("%d",&T);
while(T--)
{
scanf("%s",s);
int len = strlen(s);
// if(cnt==8708)
// puts(s);
int lena=0,lenb=0,star=0;
for(int i=0; i<len; i++)
{
if(s[i]=='(')
l[lena++]=i+1;
else if(s[i]==')')
r[lenb++]=i+1;
else
local[star++]=i+1;
}
l[lena]=0;
r[lenb]=0;
local[star]=0;
bool falg = true;
int beg=0;
bool next = true;
for(int i=0,j=0; i<lenb; i++)
{
if(l[j]<r[i]&&l[j]!=0)
j++;
else
{
if(star==beg)
falg = false;
for(int z=beg; z<star; z++)
{
if(local[z]<r[i])
{
s[local[z]-1] = '(';
beg++;
break;
}
else if(z+1==star)
falg = false;
}
}
if(j+1>lena)
{
next = false;
}
}
if(next)
for(int i=lena-1,j=lenb-1; i>=0; i--)
{
if(l[i]<r[j])
j--;
else
{
if(star==beg)
falg = false;
for(int z=star-1; z>=beg; z--)
{
if(local[z]>l[i])
{
s[local[z]-1] = ')';
star--;
break;
}
else if(z==beg)
falg = false;
}
}
}
if(falg)
{
for(int i=0; i<len; i++)
{
if(s[i]!='*')
printf("%c",s[i]);
}
puts("");
}
else
{
puts("No solution!");
}
}
return 0;
}