好一次月赛,好一次良(bian)心(tai)的题目
我与靳小才那些不得不说的故事
因为有链接(懒得写),所以我就不上题面了~
这个题目,又是一道精彩的scc模(suan)板(fa)题
嗯,他们想尽可能多拿蘑菇,嗯
那一条边我能走几次走几次,有向图,想走几次走几次……?这是什么,告诉我——SCC!!!!
是的,就是SCC!
显然(其实没那么显然),scc上的边我可以尽可能的多拿走
just like
int get_val(int i)
{
int ret = l[i].v;
int nowval = l[i].v;
while(1)
{
nowval = nowval * l[i].c;
if(!nowval) return ret;
ret += nowval;
}
}
其中,l是边,v是权值,c是那个double
好的,就是这样,我们把scc上的搞完了
那么其他的呢……?
且慢……
不不不不不不是DAG好烦啊,咱把它搞成个DAG吧
嗯,好主意
来吧
init();
for(int i = 1;i <= m;i ++)
if(scc_num[ff[i]] != scc_num[tt[i]])
build(scc_num[ff[i]],scc_num[tt[i]],vv[i],cc[i]);
恩恩
ff是记录的
恩恩
所谓……遍历边……?
恩恩
就是这样
但是,缩点之前,我们不妨先求个scc中的ans
要不,叫点权好了
嗯,是个好主意
那么怎么办呢
val,dfs吧
dfs??
枚举
嗯
枚举
对对对
枚举多棒
就是dfs()?
好像是一样呀
本来就应该一样
不过庄周梦蝶罢了
也就是这样了:
for(int u = 1;u <= n;u ++)
for(int i = first[u];~i;i = next[i])
if(scc_num[u] == scc_num[l[i].t])
val[scc_num[u]] += get_val(i);
然后,接下来是普通的言和 tarjan
int dfs_clock,dfn[MAXN];
int scc_cnt,scc_num[MAXN];
int low[MAXN];
stack <int> s;
void dfs(int u)
{
low[u] = dfn[u] = ++dfs_clock;
s.push(u);
for(int i = first[u];i != -1;i = next[i])
{
int v = l[i].t;
if(!dfn[v])
{
dfs(v);
low[u] = min(low[u],low[v]);
}
else if(!scc_num[v])
{
low[u] = min(low[u],dfn[v]);
}
}
if(low[u] == dfn[u])
{
scc_cnt ++;
while(true)
{
int x = s.top();
s.pop();
scc_num[x] = scc_cnt;
if(x == u)
break;
}
}
return;
}
最后,跑个spfa什么的就好了
是最长路,最长路哦~~
int use[MAXN],dis[MAXN];
deque <int> q;
void spfa(int S)
{
memset(use,0,sizeof(use));
memset(dis,0x80,sizeof(dis));
dis[S] = val[S];
use[S] = true;
q.push_back(S);
q.push_back(80001);
while(!q.empty())
{
int u = q.front();
q.pop_front();
use[u] = false;
for(int i = first[u];i != -1;i = next[i])
{
int v = l[i].t;
if(dis[v] < dis[u] + l[i].v + val[v])
{
dis[v] = dis[u] + l[i].v + val[v];
if(use[v])
continue;
if(dis[v] > dis[q.front()])
q.push_front(v);
else
q.push_back(v);
use[v] = true;
}
}
}
return;
}
顺带一提,ans要这样处理
int ans = 0;
for(int i = 1;i <= n;i ++)
ans = max(ans,dis[i]);
总而言之,嘛
就是这样了
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#include <stack>
using namespace std;
const int MAXN = 80000 + 5;
const int MAXM = 200000 + 5;
struct edge
{
int f,t,v;
double c;
}l[MAXM << 1];
int first[MAXN],next[MAXN << 1],tot;
void init()
{
memset(first,0xfff,sizeof(first));
tot = 0;
return;
}
void build(int f,int t,int v,double c)
{
l[++tot] = (edge){f,t,v,c};
next[tot] = first[f];
first[f] = tot;
return;
}
int dfs_clock,dfn[MAXN];
int scc_cnt,scc_num[MAXN];
int low[MAXN];
stack <int> s;
void dfs(int u)
{
low[u] = dfn[u] = ++dfs_clock;
s.push(u);
for(int i = first[u];i != -1;i = next[i])
{
int v = l[i].t;
if(!dfn[v])
{
dfs(v);
low[u] = min(low[u],low[v]);
}
else if(!scc_num[v])
{
low[u] = min(low[u],dfn[v]);
}
}
if(low[u] == dfn[u])
{
scc_cnt ++;
while(true)
{
int x = s.top();
s.pop();
scc_num[x] = scc_cnt;
if(x == u)
break;
}
}
return;
}
int val[MAXN];
int get_val(int i)
{
int ret = l[i].v;
int nowval = l[i].v;
while(1)
{
nowval = nowval * l[i].c;
if(!nowval) return ret;
ret += nowval;
}
}
int use[MAXN],dis[MAXN];
deque <int> q;
void spfa(int S)
{
memset(use,0,sizeof(use));
memset(dis,0x80,sizeof(dis));
dis[S] = val[S];
use[S] = true;
q.push_back(S);
q.push_back(80001);
while(!q.empty())
{
int u = q.front();
q.pop_front();
use[u] = false;
for(int i = first[u];i != -1;i = next[i])
{
int v = l[i].t;
if(dis[v] < dis[u] + l[i].v + val[v])
{
dis[v] = dis[u] + l[i].v + val[v];
if(use[v])
continue;
if(dis[v] > dis[q.front()])
q.push_front(v);
else
q.push_back(v);
use[v] = true;
}
}
}
return;
}
int n,m,S;
int ff[MAXM],tt[MAXM],vv[MAXM];
double cc[MAXM];
void solve()
{
scanf("%d",&S);
dfs(S);
for(int u = 1;u <= n;u ++)
for(int i = first[u];~i;i = next[i])
if(scc_num[u] == scc_num[l[i].t])
val[scc_num[u]] += get_val(i);
init();
for(int i = 1;i <= m;i ++)
if(scc_num[ff[i]] != scc_num[tt[i]])
build(scc_num[ff[i]],scc_num[tt[i]],vv[i],cc[i]);
spfa(scc_num[S]);
int ans = 0;
for(int i = 1;i <= n;i ++)
ans = max(ans,dis[i]);
printf("%d\n",ans);
return;
}
int main()
{
init();
scanf("%d %d",&n,&m);
for(int i = 1;i <= m;i ++)
{
scanf("%d %d %d %lf",&ff[i],&tt[i],&vv[i],&cc[i]);
build(ff[i],tt[i],vv[i],cc[i]);
}
solve();
return 0;
}