[COGS 165] [USACO Mar07] 奶牛交通
book
归档:
OI
flag
题目描述
题目地址:COGS
这题真是蛇,调一晚上。。码力太弱了qwq
思路
本来以为这跟HAOI2016的食物链一样,但是在WA了一次后注意到食物链计算的是经过某点的路径条数,而本题是经过某边的路径条数。
DP 方程
为了求出经过某一条边的的路径条数,可以这样:
设$f(u,v)$是经过边$u,v$的路径条数,$dp(u)$为从源点到$u$的路径条数,$rdp(v)$为从$v$到终点的路径条数,则有 $f(u,v)=dp(u)\times rdp(v)$ 最后的答案就是$\max{f(u,v)} u,v\in G$
为了实现这个操作,我们先正常建图,求出$rdp(u)$,再反向建图,求出$dp(v)$,最后对于每一条边都合并一下答案即可。
代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 5100;
struct edge
{
int f, t, d;
edge(int ff, int tt, int dd)
{
f = ff, t = tt, d = dd;
}
};
vector<edge> edges;
vector<int> g[maxn];
vector<int> rg[maxn];
int od[maxn], ind[maxn];
void addedge(int f, int t)
{
edges.push_back(edge(f, t, 1));
g[f].push_back(edges.size() - 1);
++od[f];
++ind[t];
edges.push_back(edge(t, f, 1));
rg[t].push_back(edges.size() - 1);
}
int n, m;
int dp[maxn], rdp[maxn];
int mem[maxn];
void dfs1(int f, int cur)
{
if (mem[cur])
return;
mem[cur] = 1;
if (cur == n)
{
rdp[cur] = 1;
return;
}
for (int i = 0; i < g[cur].size(); ++i)
{
int t = edges[g[cur][i]].t;
if (t == f)
continue;
dfs1(cur, t);
rdp[cur] += rdp[t];
}
}
void dfs2(int f, int cur)
{
if (mem[cur])
return;
mem[cur] = 1;
if (ind[cur] == 0)
{
dp[cur] = 1;
return;
}
for (int i = 0; i < rg[cur].size(); ++i)
{
int t = edges[rg[cur][i]].t;
if (t == f)
continue;
dfs2(cur, t);
dp[cur] += dp[t];
}
}
int main()
{
freopen("cowtraffic.in", "r", stdin);
freopen("cowtraffic.out", "w", stdout);
cin >> n >> m;
for (int i = 1; i <= m; ++i)
{
int f, t;
cin >> f >> t;
addedge(f, t);
}
for (int i = 1; i <= n; ++i)
if (ind[i] == 0)
dfs1(0, i);
memset(mem, 0, sizeof(mem));
dfs2(0, n);
int ans = 0;
for (int i = 1; i <= n; ++i)
{
for (int j = 0; j < g[i].size(); ++j)
{
edge d = edges[g[i][j]];
ans = max(ans, dp[d.f] * rdp[d.t]);
}
}
cout << ans << endl;
}
这题写的真是恶心,先是dp和rdp写反,然后还忘记记忆化。。。不管怎么说,这是一道大好题啊qwq
navigate_before
[COGS 172][IOI 2000] 回文词
Codeforces Round #419 (Div. 2) ABC
navigate_next