csu 1804 有向无环图

来源:互联网 发布:科比历年数据统计 编辑:程序博客网 时间:2024/05/22 10:32

题目地址

分析:从复杂度来看,一定不可能是枚举ij来计算。1e5的规模来看,应该是O(N)复杂度比较合适。
我是这么想的,对于三个点,假设1->2有a种走法,2->3有b种走法。那么1->3应该有a*b种走法,所以图中父亲节点一定是可以通过儿子节点的权值递推得到的。有了这个想法,那么O(N)完成这道题应该就不是梦想了。
我开了val数组,val[j]表示从j点出发的kcount(j,k)b[k],那么假设i能通向j, 那么val[i]应该等于a[i]count(i,j)val[j]+a[i]count(i,j)b[j]。把count(i,j)拆分到每次遍历的边里就行了,这样只需要加法就行了。只要每次从一个没有遍历过的点开始dfs就可以了。

代码:

/*****************************************************///#pragma comment(linker, "/STACK:1024000000,1024000000")#include <map>#include <set>#include <ctime>#include <stack>#include <queue>#include <cmath>#include <string>#include <vector>#include <cstdio>#include <cctype>#include <cstring>#include <sstream>#include <cstdlib>#include <iostream>#include <algorithm>using namespace std;#define   offcin        ios::sync_with_stdio(false)#define   sigma_size    26#define   lson          l,m,v<<1#define   rson          m+1,r,v<<1|1#define   slch          v<<1#define   srch          v<<1|1#define   sgetmid       int m = (l+r)>>1#define   LL            long long#define   ull           unsigned long long#define   mem(x,v)      memset(x,v,sizeof(x))#define   lowbit(x)     (x&-x)#define   bits(a)       __builtin_popcount(a)#define   mk            make_pair#define   pb            push_back#define   fi            first#define   se            secondconst int    INF    = 0x3f3f3f3f;const LL     INFF   = 1e18;const double pi     = acos(-1.0);const double inf    = 1e18;const double eps    = 1e-9;const LL     mod    = 1e9+7;const int    maxmat = 10;const ull    BASE   = 31;/*****************************************************/const int maxn = 1e5 + 5;std::vector<int> G[maxn];int a[maxn], b[maxn];int val[maxn];bool vis[maxn];LL ans;void dfs(int u) {    vis[u] = true;    val[u] = b[u];    for (int i = 0; i < G[u].size(); i ++) {        int v = G[u][i];        if (!vis[v]) dfs(v);        val[u] = (val[v] + val[u]) % mod;        ans = (ans + (LL)a[u] * val[v] % mod) % mod;    }}int main(int argc, char const *argv[]) {    int N, M;    while (~scanf("%d%d", &N, &M)) {        ans = 0;        for (int i = 0; i <= N; i ++) G[i].clear();        mem(val, 0); mem(vis, false); mem(a, 0); mem(b, 0);        for (int i = 1; i <= N; i ++) scanf("%d%d", a + i, b + i);        for (int i = 0; i < M; i ++) {            int u, v;            scanf("%d%d", &u, &v);            G[u].pb(v);        }        for (int i = 1; i <= N; i ++)            if (!vis[i]) dfs(i);        cout<<ans<<endl;    }    return 0;}
1 0
原创粉丝点击