ATCoderABC371CD题解
文章目录
371:
C - Make Isomorphic (atcoder.jp)
拿到这道题的时候是一脸懵的,离散数学忘得一干二净,卡在怎么去找同构上了。其实对于两个简单无向图,只要另一个图的点全排列,然后其对应的边关系加上后,这两个图长的一模一样就可以。
所以我们可以用全排列,也可以用搜索,其实都是全排列点,然后只要对应的两点与目标图的边关系不一致,就花费相应的费用将他修改为一致的,求出所有排列中花费最小的就是答案
全排列解法:
#include <iostream>
#include <algorith>
#define int long long
using namespace std;
int g[10][10];
int h[10][10];
int a[10][10];
int n;
int ans=0x3f3f3f3f;
signed main()
{
cin>>n;
int mg,mh;
int u,v;
cin>>mg;
for(int i=1;i<=mg;i++){//图G
cin>>u>>v;
g[u][v]=g[v][u]=1;
}
cin>>mh;
for(int i=1;i<=mh;i++){//图H
cin>>u>>v;
h[u][v]=h[v][u]=1;
}
for(int i=1;i<=n;i++){//花费
for(int j=i+1;j<=n;j++){
cin>>a[i][j];
a[j][i]=a[i][j];
}
}
int t[n+1];
for(int i=1;i<=n;i++) t[i]=i;
do{
int p=0;
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
if(g[i][j]!=h[t[i]][t[j]]) p+=a[t[i]][t[j]];
}
}
ans=min(p,ans);
}
while(next_permutation(t+1,t+1+n));
cout<<ans;
return 0;
}
dfs解法:
#include <iostream>
#include <algorithm>
#include <vector>
#define int long long
using namespace std;
vector<int> path;
int g[10][10];
int h[10][10];
int a[10][10];
int vis[10];
int n;
int ans=0x3f3f3f3f;
void dfs()
{
if(path.size()==n){
int t=0;
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
if(g[i][j]!=h[path[i-1]][path[j-1]]) t+=a[path[i-1]][path[j-1]];
}
}
ans=min(ans,t);
return;
}
for(int i=1;i<=n;i++)
{
if(vis[i]==0){
vis[i]=1;
path.push_back(i);
dfs();
vis[i]=0;
path.pop_back();
}
}
}
signed main()
{
int mg,mh;
int u,v;
cin>>n;
cin>>mg;
for(int i=1;i<=mg;i++){//图G
cin>>u>>v;
g[u][v]=g[v][u]=1;
}
cin>>mh;
for(int i=1;i<=mh;i++){//图H
cin>>u>>v;
h[u][v]=h[v][u]=1;
}
for(int i=1;i<=n;i++){//花费
for(int j=i+1;j<=n;j++){
cin>>a[i][j];
a[j][i]=a[i][j];
}
}
dfs();
cout<<ans;
return 0;
}
D - 1D Country (atcoder.jp)
这把d题比较简单,先用前缀和处理区间值,对于每一个查询,我们利用二分查找,找出其对应得左右端点值,然后直接利用前缀和计算,需要注意,要特判没查询到的情况,最后一个测试用例就是针对这种情况的
#include <iostream>
#define int long long
using namespace std;
const int N=2e5+10;
int x[N];
int p[N];
int n,s,q;
int l,r;
signed main()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>x[i];
for(int i=1;i<=n;i++)
{
cin>>s;
p[i]=p[i-1]+s;
}
cin>>q;
while(q--)
{
cin>>l>>r;
int ansl=-1,ansr=-1;
int L=1,R=n;
while(L<=R)
{
int mid=(L+R)/2;
if(x[mid]>=l)
{
ansl=mid;
R=mid-1;
}
else L=mid+1;
}
L=1,R=n;
while(L<=R)
{
int mid=(L+R)/2;
if(x[mid]<=r)
{
ansr=mid;
L=mid+1;
}
else R=mid-1;
}
if(ansl==-1||ansr==-1) cout<<"0"<<endl;
else cout<<p[ansr]-p[ansl-1]<<endl;
}
return 0;
}