poj 3687 Labeling Balls
题意就是给出n个球 会有k个条件限制 a b a号球会在b号前面 否则按大小顺序排 小号的在前面
首先这道题要求反向建图 让我纳闷了很久。。在什么情况下要求反向建图呢。。求人指点
学习的第一种解法并没有用到优先队列 而是模拟那个过程选取最大的没有遍历过的
那个存储的值及下标之间的关系还要再思考思考
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string.h>
#include <string>
#define eps 1e-8
#define op operator
#define MOD 10009
#define MAXN 100100
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define FOV(i,a,b) for(int i=a;i>=b;i--)
#define REP(i,a,b) for(int i=a;i<b;i++)
#define REV(i,a,b) for(int i=a-1;i>=b;i--)
#define MEM(a,x) memset(a,x,sizeof a)
#define ll __int64
using namespace std;
int rd[210];
int map[210][210];
int sta[210];
int vis[210];
int main()
{
//freopen("ceshi.txt","r",stdin);
int tc;
scanf("%d",&tc);
while(tc--)
{
int n,m;
scanf("%d%d",&n,&m);
MEM(rd,0); MEM(map,0); MEM(vis,0);
for(int i=0;i<m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
if(!map[y][x])
{
map[y][x]=1;
rd[x]++;
}
}
int top=-1;
bool flag=1;
for(int i=n;i>=1;i--)
{
int q=0;
for(int j=n;j>=1;j--)
{
if(rd[j]==0&&!vis[j])
{
q=j; break;
}
}
if(q==0)
{
flag=0;
printf("-1\n");
break;
}
vis[q]=1; sta[q]=i; //要求的是 标签对应最小重量。 拓扑序下标就是重量。。
for(int j=n;j>=1;j--)
if(map[q][j]) rd[j]--;
}
// cout<<"ttt"<<top<<endl;
if(flag)
{
for(int i=1;i<=n;i++)
printf("%d ",sta[i]);
printf("\n");
}
}
return 0;
}
然后就是借助优先队列进行解题 同样的 存储的值以及下标之间的关系需要思考
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string.h>
#include <string>
#include <queue>
#include <vector>
#define eps 1e-8
#define op operator
#define MOD 10009
#define MAXN 100100
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define FOV(i,a,b) for(int i=a;i>=b;i--)
#define REP(i,a,b) for(int i=a;i<b;i++)
#define REV(i,a,b) for(int i=a-1;i>=b;i--)
#define MEM(a,x) memset(a,x,sizeof a)
#define ll __int64
using namespace std;
int mp[210][210];
int rd[210];
int ans[210];
int main()
{
//freopen("ceshi.txt","r",stdin);
int tc;
scanf("%d",&tc);
while(tc--)
{
int n,m;
scanf("%d%d",&n,&m);
MEM(mp,0);
MEM(rd,0);
bool flag=1;
for(int i=0;i<m;i++)
{
int a,b;
scanf("%d%d",&a,&b);
if(!mp[b][a])
{
if(a==b) flag=0;
mp[b][a]=1;
rd[a]++;
}
}
// if(!flag)
// {
// printf("-1\n"); continue;
// }
priority_queue<int> q;
for(int i=1;i<=n;i++)
if(rd[i]==0) q.push(i);
// int top=0;
int index=n;
while(!q.empty())
{
int tmp=q.top();
// cout<<"top"<<top<<" "<<tmp<<endl;
q.pop();
for(int i=1;i<=n;i++)
{
if(mp[tmp][i]==1)
{
rd[i]--;
if(rd[i]==0) q.push(i);
}
}
ans[tmp]=index;
index--;
// cout<<"top"<<top<<" "<<tmp<<endl;
}
// cout<<top<<endl;
if(index>0) printf("-1\n");
else
{
printf("%d",ans[1]);
for(int i=2;i<=n;i++)
printf(" %d",ans[i]);
puts("");
}
}
return 0;
}
第二题是hdu上的一道题 4857 题意差不多
但是由于这题给的数据范围比较大 需要借助vector进行存储 数组开不了 同样的也是需要反向建图
这题与上面那题存储的方式不同 这题直接按照拓扑排序常规方法进行存储即可
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string.h>
#include <string>
#include <queue>
#define eps 1e-8
#define op operator
#define MOD 10009
#define MAXN 30010
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define FOV(i,a,b) for(int i=a;i>=b;i--)
#define REP(i,a,b) for(int i=a;i<b;i++)
#define REV(i,a,b) for(int i=a-1;i>=b;i--)
#define MEM(a,x) memset(a,x,sizeof a)
#define ll __int64
using namespace std;
int rd[MAXN];
vector<int> mp[MAXN];
int ans[MAXN];
struct cmp
{
bool operator() (int &a,int &b)
{
return a<b; //´óÖµÓÅÏÈ£»
}
};
int main()
{
//freopen("ceshi.txt","r",stdin);
int tc;
scanf("%d",&tc);
while(tc--)
{
int n,m;
scanf("%d%d",&n,&m);
MEM(rd,0);
// MEM(mp,0);
for(int i=1;i<=n;i++)
mp[i].clear();
while(m--)
{
int a,b;
scanf("%d%d",&a,&b);
mp[b].push_back(a); rd[a]++;
}
priority_queue<int,vector<int>,cmp> q;
for(int i=1;i<=n;i++)
if(rd[i]==0) q.push(i);
int top=-1;
while(!q.empty())
{
int tmp=q.top();
q.pop();
for(int i=0;i<mp[tmp].size();i++)
{
rd[mp[tmp][i]]--;
if(rd[mp[tmp][i]]==0)
q.push(mp[tmp][i]);
}
ans[++top]=tmp;
}
printf("%d",ans[n-1]);
for(int i=n-2;i>=0;i--)
printf(" %d",ans[i]);
puts("");
}
return 0;
}