输入
3 3
1 1
1 1
1 1
1 2
1 3
2 3
输出
4
并不是直接计算x~y有几条路径
而是通过叠加的方式,x~ k ~ y的值 y等于x+ k1 +k2 +k3 +y
代码
#include <stdio.h>
#include <string.h>
#define ll long long
#include <queue>
#define maxn 100010
using namespace std;
ll p=1e9+7;
int head[maxn],nex[maxn],ver[maxn],tot,d[maxn],n,m;
ll a[maxn],b[maxn],s[maxn];
void init()
{
tot=0;
memset(d,0,sizeof(d));
memset(head,0,sizeof(head));
}
void add(int u,int v)
{
tot++;
ver[tot]=v;
nex[tot]=head[u];
head[u]=tot;
}
int topsort()
{
ll res=0;
queue<int>q;
for(int i=1;i<=n;i++)
if(!d[i])q.push(i);
while(!q.empty())
{
int u=q.front();q.pop();
for(int i=head[u];i;i=nex[i])
{
int v=ver[i];
a[v]=(a[v]+a[u])%p; //这个点的值等于他之前的值叠加上来,即计算时把i到j所有都算了
if(--d[v]==0)q.push(v); //每次都将入度为0的点添加进去,
}
}
for(int i=1;i<=n;i++)res=(res+(a[i]-s[i]+p)*b[i]%p)%p; //减去s[i]是因为不能包括自己这个点的值
return res;
}
int main()
{
while(~scanf("%d %d",&n,&m))
{
init();
for(int i=1;i<=n;i++)scanf("%d%d",&a[i],&b[i]),s[i]=a[i];
for(int i=1;i<=m;i++)
{
int u,v;
scanf("%d %d",&u,&v);
add(u,v);
d[v]++;
}
printf("%lld",topsort());
}
}
#include <stdio.h>
#include <string.h>
#define ll long long
#define maxn 100010
ll p=1e9+7;
int head[maxn],next[maxn],ver[maxn],tot,d[maxn];
bool vis[maxn];
ll sum[maxn],a[maxn],b[maxn],ans;
void init()
{
tot=0;
ans=0;
memset(d,0,sizeof(d));
memset(head,0,sizeof(head));
memset(vis,0,sizeof(vis));
}
void add(int u,int v)
{
tot++;
ver[tot]=v;
next[tot]=head[u];
head[u]=tot;
}
int dfs(int u,int fa)
{
if(vis[u])return sum[u];
vis[u]=1;
ll res=0;
for(int i=head[u];i;i=next[i])
{
int v=ver[i];
if(v==fa)continue; //不能回头
res=(res+dfs(v,u))%p; //res是这条路径之后的叠加值
} //要求i到j的值,则b[i]的值不包括在内,因为还未出现到i的父亲
ans=(ans+res*a[u])%p; //res*a[u]表示这条路径的值
sum[u]=(res+b[u])%p; //res+b[u]为之后的b[v]值和当前b[u]叠加,添加到它的父亲上
return sum[u];
}
int main()
{
int n,m;
while(~scanf("%d %d",&n,&m))
{
init();
for(int i=1;i<=n;i++)scanf("%d%d",&a[i],&b[i]);
for(int i=1;i<=m;i++)
{
int u,v;
scanf("%d %d",&u,&v);
add(u,v);
d[v]++;
}
for(int i=1;i<=n;i++)
{
if(!d[i])dfs(i,0);
}
printf("%lld\n",ans);
}
}