题目链接:Min Cost Cycle
题目大意:洛谷
题解:远古时期写的题现在啥都不会了。
将(A,B)排序取前(n)个,对于每一个点(00)表示(A,B)都没有选,(01)表示(A)没选(B)选了,以此类推,所以有(1)恒比(0)小,所以考虑构造方案。
首先,每一个数的状态不外乎 4 个,如果有(00)或(11)的话可以将(01,10)串在一起,所以这种情况下可以直接输出前(n)个的和。
否则的话,判断能否构成环,如果不可以的话就往后找,找到几个来替换出(00)或(11)就可以了。
时间复杂度(O(nlog n)).
代码:
#include <set>
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
#define ll long long
#define Maxn 100000
set<pair<int,int> > st;
int a[Maxn+5],b[Maxn+5];
int x[Maxn+5];
int have[Maxn+5];
int mn(int a,int b){
return a<b?a:b;
}
int main(){
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d%d",&a[i],&b[i]);
st.insert(make_pair(a[i],i<<1));
st.insert(make_pair(b[i],(i<<1)|1));
}
set<pair<int,int> >::iterator it;
int now=n,tmp;
it=st.begin();
ll sum=0;
while(now--){
tmp=(it->second)>>1;
sum+=(it->first);
if((it->second)&1){
x[tmp]+=1;
}
else{
x[tmp]+=2;
}
it++;
}
for(int i=1;i<=n;i++){
have[x[i]]++;
}
if(have[0]||(!have[2])||(!have[1])){
cout<<sum<<endl;
return 0;
}
if(((it->second)>>1)==tmp){
it--;
int now_1=(it->first);
it--;
int now_2=(it->first);
it++;
it++;
int now_3=(it->first);
it++;
int now_4=(it->first);
sum+=mn(now_3-now_2,now_4-now_1);
cout<<sum<<endl;
return 0;
}
it--;
x[tmp]=0;
sum-=(it->first);
it++;
while(it!=st.end()){
tmp=(it->second)>>1;
if(x[tmp]){
sum+=(it->first);
break;
}
it++;
}
cout<<sum<<endl;
return 0;
}