Input
Output對于每組數據,輸出一個整數表示要求的值。Sample Input
3 3 1 1 1 1 1 1 1 2 1 3 2 3 2 2 1 0 0 2 1 2 1 2 2 1 500000000 0 0 500000000 1 2
Sample Output
4 4 250000014
Hint
?
?
思路:
由有向圖拓撲序的性質可以知道,拓撲序在后的節點是沒有指向拓撲序在前的節點。
那么我們在對整個圖進行拓撲的時候,把起始點 x 的a[x] 值 附加到 這個邊的終點 y 的a[y] 值上。
并且對于每一個邊,我們維護一個 long long 類型的 答案 ans,ans+= a[x]*b[y]? (? 邊 是 x ~> y )
那么這里就介紹剛剛我們為什么要附加數值a[x] 到a[y]上。
如果由三個點? x y z ,由如下的連接關系 x ~> y ~> z 那么x到y的邊我們會算一次對答案的貢獻值,y到z的邊我們也會算一次。
還有一個x到z的邊,我們仍然需要算。因為x可以到達z,那么如果我們在拓撲的時候把a[y]加上a[x] 時, 我們在算 b到z 的邊的時候就順便的加上了a到z的邊。
因為x 的拓撲優先級比y高,并且x可以到達y,那么x就可以到達y能到達的所有邊,那么就解釋了這樣做的原因。
這樣做的時間復雜度就會轉化為 O ( N )?
主要是理解后就很好寫代碼,可以自己動手畫圖理解一下上面 講的內容。
?
實現細節見ac代碼:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <queue> #include <stack> #include <map> #include <set> #include <vector> #include <iomanip> #define ALL(x) (x).begin(), (x).end() #define rt return #define dll(x) scanf("%I64d",&x) #define xll(x) printf("%I64d\n",x) #define sz(a) int(a.size()) #define all(a) a.begin(), a.end() #define rep(i,x,n) for(int i=x;i<n;i++) #define repd(i,x,n) for(int i=x;i<=n;i++) #define pii pair<int,int> #define pll pair<long long ,long long> #define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0) #define MS0(X) memset((X), 0, sizeof((X))) #define MSC0(X) memset((X), '\0', sizeof((X))) #define pb push_back #define mp make_pair #define fi first #define se second #define eps 1e-6 #define gg(x) getInt(&x) #define db(x) cout<<"== [ "<<x<<" ] =="<<endl; using namespace std; typedef long long ll; ll gcd(ll a,ll b){return b?gcd(b,a%b):a;} ll lcm(ll a,ll b){return a/gcd(a,b)*b;} ll powmod(ll a,ll b,ll MOD){ll ans=1;while(b){if(b%2)ans=ans*a%MOD;a=a*a%MOD;b/=2;}return ans;} inline void getInt(int* p); const int maxn=100010; const int inf=0x3f3f3f3f; /*** TEMPLATE CODE * * STARTS HERE ***/ std::vector<int> son[maxn]; const ll mod=1e9+7ll; ll ans=0ll; ll a[maxn]; ll b[maxn]; ll num[maxn]; int du[maxn]; int main() {// freopen("D:\\common_text\\code_stream\\in.txt","r",stdin);//freopen("D:\\common_text\\code_stream\\out.txt","w",stdout); gbtb;int n,m;while(cin>>n>>m){repd(i,1,n){son[i].clear();}MS0(du);MS0(num);repd(i,1,n){cin>>a[i]>>b[i];}int x,y;repd(i,1,m){cin>>x>>y;son[x].push_back(y);du[y]++;}queue<int> q;repd(i,1,n){if(!du[i]){q.push(i);}}ans=0ll;while(q.size()){int temp=q.front();q.pop();for(auto x:son[temp]){ans=(ans+(a[temp]*b[x])%mod+mod)%mod;a[x]+=a[temp];a[x]=(a[x]+mod)%mod;du[x]--;if(!du[x]){q.push(x);}}}cout<<ans<<endl;}return 0; }inline void getInt(int* p) {char ch;do {ch = getchar();} while (ch == ' ' || ch == '\n');if (ch == '-') {*p = -(getchar() - '0');while ((ch = getchar()) >= '0' && ch <= '9') {*p = *p * 10 - ch + '0';}}else {*p = ch - '0';while ((ch = getchar()) >= '0' && ch <= '9') {*p = *p * 10 + ch - '0';}} }
?