Inputcopy | Outputcopy |
---|---|
3 3 8 0 10 -2 1 4 10 11 20 7 -1 9 1 2 3 5 -2 3 6 -1 2 1 3 3 -1 2 4 4 0 8 2 2 5 5 -1 3 -2 1 0 -2 0 -5 -3 | 12 2 6 5 1 7 8 10 1 6 5 2 3 4 -6 5 1 4 2 |
大致题意:
让你找2*n个点加起来的权值和最小,然后输出,并且输出每条边的两个端点,端点不能用重合,边只能有平行边
解题思路:
起初被这个平行边搞得头疼,明知道是贪心又不敢贪,后来发现压根不用管,权值和肯定是直接排序取前2*n个权值加起来,边就是对给定下标排序,然后按一个前一个后输出,输出的结构体里的次序。所以此题为结构体排序,然后就是还是搞不懂为什么这样不会影响答案次序~恼,大胆猜测就是下标优先,妥妥地贪心。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N = 2e5+10;
map<int,int> mp;
struct node
{
int index,pos,val;
}p[N];
bool cmpval(struct node a,struct node b){return a.val < b.val;}
bool cmppos(struct node a,struct node b){return a.pos < b.pos;}
signed main()
{
int t;cin>>t;
while(t--){
int n,m,ans=0;cin>>n>>m;
for(int i=1;i<=m;i++){
cin>>p[i].pos>>p[i].val;
p[i].index = i;
}
sort(p+1,p+m+1,cmpval);
for(int i=1;i<=2*n;i++)
ans+=p[i].val;
cout<<ans<<"\n";
sort(p+1,p+2*n+1,cmppos);
for(int i=1;i<=n;i++)
cout<<p[i].index<<" "<<p[2*n-i+1].index<<"\n";
cout<<"\n";
}
return 0;
}