P5318 【深基18.例3】查找文献
思路
bfs和dfs的模板题
实现
#include<bits/stdc++.h>
using namespace std;
int n,m;
vector<int> a[1000010];
bool visit[1000010];
void dfs(int x,int depth)
{
visit[x] = 1;
if(depth==n)
{
cout<<x<<" ";
return ;
}
cout<<x<<" ";
for(int i=0;i<a[x].size();i++)
if(!visit[a[x][i]]) dfs(a[x][i],depth+1);
}
void bfs()
{
queue<int> q;
q.push(1);
visit[1] = 0;
while(!q.empty())
{
int s = q.front();
q.pop();
cout<<s<<" ";
for(int i=0;i<a[s].size();i++)
{
if(visit[a[s][i]])
{
q.push(a[s][i]);
visit[a[s][i]] = 0;
}
}
}
}
int main()
{
cin>>n>>m;
int t1,t2;
for(int i=1;i<=m;i++)
{
cin>>t1>>t2;
a[t1].push_back(t2);
}
for(int i=1;i<=n;i++)
sort(a[i].begin(),a[i].end());
dfs(1,1);
cout<<endl;
bfs();
}
P3916 图的遍历
思路
反向建立边,从节点最大的开始dfs,把沿途所有点的值都修改
实现
#include<bits/stdc++.h>
using namespace std;
#define MAXL 100010
int N, M, A[MAXL];
vector<int> G[MAXL];
void dfs(int x, int d) {
if(A[x]) return;
A[x] = d;
for(int i=0; i<G[x].size(); i++)
dfs(G[x][i], d);
}
int main() {
int u, v;
scanf("%d%d", &N, &M);
for(int i=1; i<=M; i++) {
scanf("%d%d", &u, &v);
G[v].push_back(u);
}
for(int i=N; i; i--) dfs(i, i);
for(int i=1; i<=N; i++) printf("%d ", A[i]);
printf("\n");
return 0;
}
P1113 杂务
思路
拓扑排序
本题数据特殊,是有序的。因此可以在输入时处理,建图意义不大
实现
//来自Nishikino_Curtis
#include<bits/stdc++.h>
using namespace std;
int n,l,t,ans[10005],maxans;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;++i){
scanf("%d",&i);
scanf("%d",&l);
int tmp=0;
while(scanf("%d",&t)&&t)
tmp=max(ans[t],tmp);
ans[i]=tmp+l;
maxans=max(ans[i],maxans);
}
printf("%d\n",maxans);
return 0;
}
P4017 最大食物链计数
思路
边拓扑排序边维护从生产者到该节点有多少条路(路的条数等于所有指向它的节点的路的条数之和)
实现
一个有错误的实现 有空改改
#include<bits/stdc++.h>
using namespace std;
const int N = 5010;
int h[N], e[N], ne[N], idx;
int q[N], d[N];
int ans[N];
int n,m;
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}
int topsort()
{
int hh = 0, tt = -1;
// d[i] 存储点i的入度
for (int i = 1; i <= n; i ++ )
if (!d[i])
q[ ++ tt] = i;
while (hh <= tt)
{
int t = q[hh ++ ];
// cout<<endl;
// cout<<t<<" ";
for (int i = h[t]; i != -1; i = ne[i])
{
int j = e[i];
// cout<<j;
ans[j] += ans[t];
ans[j]%=80112002;
if (-- d[j] == 0)
q[ ++ tt] = j;
}
}
// 如果所有点都入队了,说明存在拓扑序列;否则不存在拓扑序列。
return q[tt];
}
int main()
{
idx = 0;
memset(h, -1, sizeof h);
cin>>n>>m;
vector<bool> eat(n+1,0);
int t1,t2;
for(int i=0;i<m;i++)
{
scanf("%d%d",&t1,&t2);
d[t2]++;
add(t1,t2);
eat[t1] = 1;
}
int res = 0;
ans[1] = 1;
topsort();
for(int i=1;i<=n;i++)
{
if(!eat[i])
res = (ans[i]+res)%80112002;
}
cout<<res;
return 0;
}
P1807 最长路
思路
给边权求相反数,转换为求最短路问题
实现
#include<bits/stdc++.h>
using namespace std;
int main(){
int dis[50001],w[50001],n,m,minn,f[50001][3];
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
dis[i]=w[i]=100000000;
f[i][1]=f[i][2]=0;
}
for(int i=1;i<=m;i++){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
f[i][1]=a,f[i][2]=b,w[i]=-c;
}
dis[1]=0;
for(int i=1;i<=n-1;i++){
for(int j=1;j<=m;j++){
dis[f[j][2]]=min(dis[f[j][2]],dis[f[j][1]]+w[j]);
}
}
if(dis[n]!=0)
printf("%d",-dis[n]);
else printf("-1");
return 0;
}
P2853 [USACO06DEC]Cow Picnic S
思路
从k个奶牛出发,dfs且记录每一个牧场被遍历的次数。被遍历次数等于k的牧场符合条件。
实现
#include<bits/stdc++.h>
using namespace std;
bool vis[1010];
int k,n,m,ans;
int mk[1010],a[1010];
vector <int> b[1010];
void dfs(int x)
{
vis[x]=1; mk[x]++;
for(int i=0;i<b[x].size();i++)
if(!vis[b[x][i]])
dfs(b[x][i]);
}
int main()
{
int x,y;
cin>>k>>n>>m;
for(int i=1;i<=k;i++) cin>>a[i];
for(int i=1;i<=m;i++)
{
cin>>x>>y;
b[x].push_back(y);
}
for(int i=1;i<=k;i++)
{
for(int j=1;j<=n;j++)
vis[j]=0;
dfs(a[i]);
}
for(int i=1;i<=n;i++)
if(mk[i]==k) ans++;
cout<<ans;
return 0;
}
P1347 排序
思路
自己写出来不对 绿题果然还是难的 = =
来自题解区 mydiplomacy
- 条件有矛盾:没有点入度为0,或者最后在队列里的节点数<n
- 条件不足:有不止一个点入度为零,或当取同一个队首u时有不止一个v的入度变成了零
- 排序成功:非上两种情况
实现
来自题解区 mydiplomacy
#include<bits/stdc++.h>
using namespace std;
const int maxn=30,maxm=905;
struct Node
{
int v;
Node *next;
}*h[maxn],pool[maxm];
int tot;
int du[maxn];
int q[maxn],head,tail;
int n,m;
void addEdge(int u, int v)
{
Node *p=&pool[++tot];
p->v=v; p->next=h[u]; h[u]=p;
}
int toposort() //返回值为1代表成立,返回值为0代表条件不足,返回值为-1代表条件矛盾
{
int temp=0;
int f=0;
for(int i=1;i<=n;i++)
{
if(du[i]==0)
{
q[tail++]=i;
temp++;
}
}
if(temp>1)
f=1;
while(head<tail)
{
temp=0;
int u=q[head++];
for(Node *p=h[u];p;p=p->next)
{
du[p->v]--;
if(du[p->v]==0)
{
q[tail++]=p->v;
temp++;
}
}
if(temp>1)
f=1;
}
if(tail!=n)
return -1;
else
if(f==1)
return 0;
else return 1;
}
struct Edge
{
int u,v;
}a[maxm];
int main()
{
cin>>n>>m;
for(int i=1;i<=m;i++)
{
char aa,bb,cc;
cin>>aa>>bb>>cc;
a[i].u=aa-'A'+1; a[i].v=cc-'A'+1;
}
for(int i=1;i<=m;i++)
{
addEdge(a[i].u,a[i].v);
head = tail = 0;
memset(du,0,sizeof(du));
for(int j=1;j<=i;j++) du[a[j].v]++;
int flag=toposort();
if(flag==1)
{
cout<<"Sorted sequence determined after "<<i<<" relations: ";
for(int j=0;j<=n-1;j++)
{
cout<<(char)(q[j]+'A'-1);
}
cout<<'.'<<endl;
return 0;
}
else if(flag==0) continue;
else
{
cout<<"Inconsistency found after ";
cout<<i<<" relations."<<endl;
return 0;
}
}
cout<<"Sorted sequence cannot be determined."<<endl;
return 0;
}
P1983 [NOIP2013 普及组] 车站分级
思路
建图时添加从停靠站到未停靠站的边,拓扑排序记录一共有几层
实现
来自 黄毛猫_HYX
#include<bits/stdc++.h>
#define N 1005
using namespace std;
int n,m,ans,st[N],s,tuopu[N][N],de[N],tt[N],top;
bool is[N],bo[N];
int main() {
scanf("%d %d",&n,&m);
for(int i=1;i<=m;i++) {
memset(is,0,sizeof(is));//is表示是否是停靠站
scanf("%d",&s);
for(int j=1;j<=s;j++)
scanf("%d",&st[j]),is[st[j]]=true;
for(int j=st[1];j<=st[s];j++)
if(!is[j]) //枚举站点,若不是已停靠的就小于所有停靠站的等级
for(int k=1;k<=s;k++) //枚举已停靠站点
if(!tuopu[j][st[k]]) tuopu[j][st[k]]=1,de[st[k]]++;//tuopu[i][j]表示j>i的级别,如上
}
do{
top=0;
for(int i=1;i<=n;i++)
if(de[i]==0&&!bo[i]) {
tt[++top]=i,bo[i]=true;//开始将出度为0的点删掉
}
for(int i=1;i<=top;i++)
for(int j=1;j<=n;j++)
if(tuopu[tt[i]][j]) tuopu[tt[i]][j]=0,de[j]--;//去边去点
ans++;
} while(top);
printf("%d",ans-1);//最后一次什么点都没有会多算一次(自行理解)
return 0;
}
欢迎指正