题目链接: http://codeforces.com/contest/1095
D. Circular Dance
题意: 给出N个人身后所接着两个人,两个顺序不一定,问是否存在一群人围成一圈的排列方式
思路:
我们可以直接假设1号后面的那个人,只要确定的1个,接下来全部都确定了
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+5;
int l[maxn],r[maxn];
int n;
int check(int fa,int ch)
{
vector<int>ans;
//ans.push_back(1);
for(int i=1;i<=n;i++)
{
int nxt=0;
if(l[fa]==ch)
nxt=r[fa];
else if(r[fa]==ch)
nxt=l[fa];
else{
return 1;
}
ans.push_back(nxt);
fa=ch;
ch=nxt;
}
for(auto it: ans)
{
cout<<it<<" ";
}
cout<<endl;
return 0;
}
int main()
{
//int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>l[i]>>r[i];
}
if(n==3){
cout<<"1 2 3"<<endl;
return 0;
}
if(check(1,l[1]))
{
check(1,r[1]);
}
return 0;
}
E. Almost Regular Bracket Sequence
题意: 问修改一处地方后括号的合法的个数
思路: 我们可以对左括号进行一次前缀和
l
[
]
l[ ]
l[],在这过程中遇左+1,遇右-1,右括号一次后缀和
r
[
]
r[ ]
r[],与前面相反,然后枚举每个位置,若当前位置s为左括号,若l[s-1]-1==r[s+1],则ans++;若为右括号,相反
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+5;
int s1[maxn],s2[maxn];
bool v1[maxn],v2[maxn];
int main()
{
int n;
cin>>n;
string s;
cin>>s;
s=' '+s;
for(int i=1;i<=n;++i)
{
s1[i]=s1[i-1]+(s[i]=='(' ? 1 : -1);
}
for(int i=n;i>0;i--)
{
s2[i]=s2[i+1]+(s[i]==')' ? 1 : -1);
}
for(int i=n+1;i>0;i--)
{
if(s2[i]>=0)
v2[i]=1;
else
break;
}
for(int i=0;i<=n;i++)
{
if(s1[i]>=0)
v1[i]=1;
else
break;
}
/*
for(int i=1;i<=n;i++)
cout<<v1[i]<<endl;
for(int i=1;i<=n;i++)
cout<<v2[i]<<endl;
*/
int ans=0;
for(int i=1;i<=n;++i)
{
if(v1[i-1]&&v2[i+1])
{
if(s[i]=='(')
{
if(s1[i-1]-1==s2[i+1])
ans++;
//cout<<ans<<endl;
}
else
{
if(s1[i-1]+1==s2[i+1])
ans++;
}
}
}
cout<<ans<<endl;
return 0;
}
F. Make It Connected(最小生成树?)
题意: 给定 n 个点,每个点有点权,连结两个点花费的代价为两点的点权和。另外有 m 条特殊边,参数为 x,y,z。意为如果你选择这条边,就可以花费 z 的代价将点 x 和点 y 连结起来,当然你也可以不选择这条边。求使整个图联通的最小代价
思路:
首先我们找出点权值最小的那道题,我们可以知道将它与其他连接,在没有使用特殊边是代价最小的,我们可以连起来后,对每条边(包括特俗边)的权值进行排序,逐一加算入总和,并用并查集维护,防止加上重复路径的其他权值
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f3f3f3f
#define mp make_pair
#define x first
#define y second
using namespace std;
typedef long long ll;
const int maxn=2e5+5;
ll a[maxn];
typedef pair<ll,pair<int,int>>edge;
int fa[maxn];
int fid(int x)
{
if(x==fa[x])
return x;
return fa[x]=fid(fa[x]);
}
bool me(int x,int y)
{
x=fid(x);
y=fid(y);
if(x==y)
return 0;
fa[x]=y;
return 1;
}
int main()
{
int n,m;
ll minn=INF;
int id;
//cout<<INF<<endl;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
if(minn>a[i])
{
minn=a[i];
id=i;
}
//minn=min(minn,a[i]);
}
for(int i=1;i<=n;i++)
fa[i]=i;
vector<edge>es(m);
for(int i=0;i<m;i++)
{
scanf("%d %d %lld",&es[i].y.x,&es[i].y.y,&es[i].x);
}
for(int i=1;i<=n;i++)
{
if(i!=id)
es.push_back(mp(a[i]+a[id],mp(i,id)));
}
sort(es.begin(),es.end());
ll ans=0;
for(auto it: es)
{
if(me(it.y.x,it.y.y))
{
ans+=it.x;
}
}
printf("%lld\n",ans);
return 0;
}