BZOJ 3890 Usaco2015 Jan Meeting Time 拓扑图DP

题目大意

题上的中文题意太不明确了。。。
给出一个拓扑图,每条有向边有两个权值,有两个人从1出发到n,分别走这两种权值。问有没有权值使得这两个人都能走过这些权值到达n。

思路

看懂了题之后就水了。维护两个数组表示从1号节点是否能够通过i的权值到达j。然后做拓扑图DP。

CODE

#define _CRT_SECURE_NO_WARNINGS

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 110
#define MAXE 10010
#define INF 0x3f3f3f3f
using namespace std;

int points,edges;
int head[MAX],total;
int _next[MAXE],aim[MAXE];
int length[MAXE],_length[MAXE];

inline void Add(int x,int y,int len,int _len)
{
    _next[++total] = head[x];
    aim[total] = y;
    length[total] = len;
    _length[total] = _len;
    head[x] = total;
}

int _in[MAX];
queue<int> q;
bool f[MAX][MAXE],g[MAX][MAXE];

bool v[MAX];

int main()
{
    cin >> points >> edges;
    for(int x,y,z,l,i = 1; i <= edges; ++i) {
        scanf("%d%d%d%d",&x,&y,&z,&l);
        Add(x,y,z,l);
        ++_in[y];
    }
    for(int i = 1; i <= points; ++i)
        if(!_in[i])
            q.push(i);
    f[1][0] = g[1][0] = true;
    while(!q.empty()) {
        int x = q.front(); q.pop();
        for(int i = head[x]; i; i = _next[i]) {
            for(int j = 0; j + length[i] < MAXE; ++j)   f[aim[i]][j + length[i]] |= f[x][j];
            for(int j = 0; j + _length[i] < MAXE; ++j)  g[aim[i]][j + _length[i]] |= g[x][j];
            if(!--_in[aim[i]])
                q.push(aim[i]);
        }
    }
    for(int i = 0 ; i < MAXE; ++i)
        if(f[points][i]&g[points][i]) {
            cout << i << endl;
            return 0;
        }
    puts("IMPOSSIBLE");
    return 0;
}

你可能感兴趣的:(USACO,bzoj,拓扑图DP)