E - Egor in the Republic of Dagestan

线性dp的本质其实就是DAG上递推,而最短路的本质其实就是dp,而最短路的dp其实就是处理有环图的一种dp处理方法。首先最短路是基于贪心的dp,如果是不基于贪心,其实本质就是跑n次o(m)的dp转移,但是由于有了贪心加上优先队列优化,就成了m*logn的,而这种贪心应用于某些有环的dp上就成了最短路dp问题。

题意:
给出 n 个点和 m 条边的有向图,每条边的长度为 1 ,有一个属性由 0 或 1 表示,现在需要给每个节点赋值,使得:
1.如果点 u 的权值为 0 ,则 u 只能走 ( u , v ) 且这条边的属性为 0 的边。
2.如果点 u 的权值为 1 ,则 u 只能走 ( u , v ) 且这条边的属性为 1 的边
问如何赋值能让点 1 到点 n 的最短路最大,输出一种构造方案。
思路:
这明显是最短路dp,而且得倒着跑,从n跑到1,然后dis[i][j]代表到达第i点且第i个点选择为j状态(0或者1)的最短路的最大值。明显,如果从1个点转移到另一个点,贪心的想肯定是得把这个点的max(dis[i][0],dis[i][1])作为当前的最短路,因为这样才能使得最短路最大。然后就跑最短路就行,因为边权为1,所以直接bfs即可。最后输出构造方案,就贪心即可。

#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#include<cstring>
using namespace std;
const int MAX_N=501000;
const int INF=0x3f3f3f3f;
vector<int>v[MAX_N],w[MAX_N];
struct skt{
 int x,y;
};
int dis[MAX_N][2];
int tox[MAX_N][2],toy[MAX_N][2];
int n;
int b[MAX_N];
void bfs(){
 int i;
 queue<skt>q;
 skt t;
 memset(dis,INF,sizeof(dis));
 t.x=n,t.y=0;
 q.push(t);
 t.x=n,t.y=1;
 q.push(t);
 dis[n][0]=0;
 dis[n][1]=0;
 while(!q.empty()){
  skt t=q.front();
  q.pop();
  int x=t.x,d=t.y;
  for(i=0;i<v[x].size();i++){
   int y=v[x][i];
   int k=w[x][i];
   if(dis[y][k]>max(dis[x][d],dis[x][d^1])+1){
    dis[y][k]=max(dis[x][d],dis[x][d^1])+1;
    tox[y][k]=x;
    if(dis[x][d]>dis[x][d^1])
    toy[y][k]=d;
    else
    toy[y][k]=d^1;
    skt t;t.x=y,t.y=k;
    q.push(t);
   }
  }
 }
}
void dfs(int x,int y){
 if(x==0&&y==0)
 return ;
 b[x]=y;
 dfs(tox[x][y],toy[x][y]);
}
int main(void){
 int m,i,x,y,t;
 scanf("%d%d",&n,&m);
 for(i=1;i<=m;i++){
  scanf("%d%d%d",&x,&y,&t);
  if(x==y)
  continue;
  v[y].push_back(x);
  w[y].push_back(t);
 }
 bfs();
 if(dis[1][0]==INF||dis[1][1]==INF)
 printf("-1\n");
 else
 printf("%d\n",max(dis[1][0],dis[1][1]));
 for(i=1;i<=n;i++){
  if(dis[i][0]>dis[i][1])
  b[i]=0;
  else
  b[i]=1;
  printf("%d",b[i]);
 }
 return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值