上题主要是选取一个贪心策略,如果尽力把序号小的菜肴放到前面,则操作起来很难,如果反过来想,将序号大的尽可能放后面,则通过拓扑排序建立反向图,再输出则为答案
代码如下
#include<bits/stdc++.h>
#define ll long long
#define max_int 2147483647
#define max_ll 9223372036854775807
using namespace std;
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
int all;
cin>>all;
while(all--){
//priority_queue<int,vector<int>,less<int> >q;
priority_queue<int,vector<int>,less<int>>q;
int n,m;
cin>>n>>m;
vector<int>graph[n+1];
vector<int>in(n+1);
vector<int>answer;
for(int i=0,a,b;i<m;++i){
cin>>a>>b;
graph[b].push_back(a);
++in[a];
}
for(int i=1;i<=n;++i){
if(!in[i]) q.push(i);
}
while(q.size()){
int u=q.top();q.pop();answer.push_back(u);
for(int v:graph[u]){
in[v]--;
if(!in[v]) q.push(v);
}
}
if(answer.size()!=n) cout<<"Impossible!"<<endl;
else{
for(int i=n-1;i>=0;--i) cout<<answer[i]<<' ';
cout<<endl;
}
}
return 0;
}
这个是二分图最大匹配算法。
-
初始化
- 首先,为每个顶点标记为未访问过,并将其对应的匹配顶点初始化为未匹配状态。
-
寻找增广路径
- 从一个未匹配的顶点开始,尝试寻找一条增广路径。增广路径是指从一个未匹配的顶点出发,交替经过未匹配边和已匹配边,最终到达另一个未匹配的顶点的路径。
- 如果找到了增广路径,就可以通过交换路径上的边的匹配状态,来增加匹配的边数。
-
更新匹配
- 如果找到了增广路径,就更新匹配状态,将路径上的边的匹配状态进行交换。
- 如果没有找到增广路径,就标记当前顶点为已访问过,并尝试从下一个未匹配的顶点开始寻找增广路径。
-
重复步骤 2 和 3,直到找不到增广路径为止。