首先 感謝 xiaoyao24256大佬 給個人blog(雖然只用一天QWQ)ios
這幾天來到了浙江集訓 爽爆(假的qwq)c++
儘管這幾天學到了好多知識 但我仍是個蒟蒻555算法
從5.29的ACM賽先說吧數組
比賽名稱叫ACM歡樂賽,作題不歡樂,可是吃KFC吃的很歡樂嘿嘿嘿優化
一開始的時候 咱們小組比其餘小組早A了前2道題(雖然不是最先)ui
而後而後而後我就很開心spa
因而咱們就卡在了第三題……code
咱們組一個大佬想出來了一個gcd的算法(我不會告訴你他就是給我號的人)blog
結果不知道什麼玄學緣由 咱們組否定了這個算法 去剛第四題排序
爲何要否定呢?我也不知道啊……鬼知道那就是正解qwq
附上核心代碼
1 read(p) , read(q) , read(b); 2 3 register ll Gcd = gcd(p,q); 4 q /= Gcd; 5 Gcd = b; 6 7 for(; q!=-1; ) { 8 Gcd = gcd(q,Gcd); 9 q /= Gcd; 10 if(Gcd == 1) break; 11 } 12 13 if(q == 1) puts("Finite"); 14 else puts("Infinite");
第四題……不想說什麼了
我推了快1個小時的數學解
而後推出來了一個玄學的東西:
if len%4 == 1 輸出頭尾各一個數
if len%4 == 2 輸出頭尾各2個數
if len%4 == 3 輸出第一個數、第三個數、倒1、倒三這些數
if len%4 == 0 輸出全部數
正當我推得很是開心的時候 驗證了下len=12的狀況
而後就發現這個作法是錯誤的
因而 MMP ……
比賽結束以後我才發現這道是一道很是!水的!區間DP
哇哇哇氣死了
依然附上代碼
1 for(register int i=n-1; i>=1; i--) { 2 for(register int j=i+1; j<=n; j++) { 3 f[i][j] = f[i][j-1] ^ f[i+1][j]; 4 g[i][j] = maxest(f[i][j],g[i][j-1],g[i+1][j]); 5 } 6 }
咱們最後選擇直接去看第7題(垃圾AtCoder)
想出了兩個相似正解的方法
嗯其實不是正解 最後測了WA的不要不要的
逃)
嗯那兩個算法就是打表和隨機數
事實證實打表能過更多的點
誒呀打表是我想出來的~
我以爲我能夠把表交上來
嗯算了太大了不交了qwq
我不會告訴你我其實在湊字數
好了好了咱們來說一下正事吧
對這就是一個很神奇的東西
咱們先來引入一個題目:戳我
假如說這道題目沒有修改這這個操做,咱們用前綴和維護一下就好了
加了修改以後,咱們能想到的最樸素的作法是什麼呢?
固然就是枚舉 L - R 之間每一個數而後加上x
求和也是一項一項加起來,這樣複雜的是O(N^2)的
一看數據,喊出GG~
那咱們有沒有什麼奇技淫巧下降複雜度呢?
線段樹就是爲了這個而生的。
就讓我來簡介一下線段樹吧:
線段樹是一個二叉樹,每一個子節點裏存放一段區間的左右邊界還有子節點的信息,能夠是一段區間的和、最大值、最小值等等等等
爲了更好的理解線段樹,我厚顏無恥的拿了網上某個大佬的圖來解釋
算了中間一堆能夠介紹的如今也寫不了了,就不介紹了,有沒感受本身期待了半天卻……嗯哼~
我直接貼代碼了欸嘿
1 // luogu-judger-enable-o2 2 #include <iostream> 3 #include <cstdio> 4 5 using namespace std; 6 7 typedef long long ll; 8 const int Maxn = 400010; 9 int n , m; 10 int a[Maxn]; 11 struct SegmentTree { 12 ll sum; /* 1的總數 */ 13 ll tag; /* 標記 */ 14 int leftbound; 15 int rightbound; 16 } Tree[Maxn]; 17 18 inline void Build(int root, int left , int right) { 19 20 Tree[root].leftbound = left; 21 Tree[root].rightbound = right; 22 if(left == right) Tree[root].sum = a[left]; 23 else { 24 register int Mid = ( left + right ) / 2; 25 Build(root*2,left,Mid); 26 Build(root*2+1,Mid+1,right); 27 Tree[root].sum = Tree[root*2].sum + Tree[root*2+1].sum; 28 } 29 30 } 31 32 inline void Downtag(int root) { 33 34 if(Tree[root].tag) { 35 Tree[root*2].tag += Tree[root].tag; 36 Tree[root*2+1].tag += Tree[root].tag; 37 Tree[root*2].sum += ( Tree[root*2].rightbound - Tree[root*2].leftbound + 1 ) * Tree[root].tag; 38 Tree[root*2+1].sum += ( Tree[root*2+1].rightbound - Tree[root*2+1].leftbound + 1 ) * Tree[root].tag; 39 Tree[root].tag = 0; 40 } 41 42 } 43 44 inline void Modify(int root , int left , int right , int delta) { 45 46 if(Tree[root].leftbound >= left && Tree[root].rightbound <= right) { 47 Tree[root].tag += delta; 48 Tree[root].sum += ( Tree[root].rightbound - Tree[root].leftbound + 1 ) * delta; 49 } else { 50 Downtag(root); 51 register int Mid = ( Tree[root].leftbound + Tree[root].rightbound ) / 2; 52 if(left <= Mid) Modify(root*2,left,right,delta); 53 if(right > Mid) Modify(root*2+1,left,right,delta); 54 Tree[root].sum = Tree[root*2].sum + Tree[root*2+1].sum; 55 } 56 57 } 58 59 inline ll Query(int root , int left , int right) { 60 61 if(Tree[root].leftbound >= left && Tree[root].rightbound <= right) { 62 return Tree[root].sum; 63 } else { 64 Downtag(root); 65 register ll ans = 0; 66 register int Mid = ( Tree[root].leftbound + Tree[root].rightbound ) / 2; 67 if(left <= Mid) ans += Query(root*2,left,right); 68 if(right > Mid) ans += Query(root*2+1,left,right); 69 return ans; 70 } 71 72 } 73 74 int main() { 75 76 scanf("%d%d",&n,&m); 77 78 for(register int i=1; i<=n; i++) 79 scanf("%d",&a[i]); 80 81 Build(1,1,n); 82 83 for(register int i=1,x,y,z,k; i<=m; i++) { 84 scanf("%d%d%d",&z,&x,&y); 85 if(z == 1) { 86 scanf("%d",&k); 87 Modify(1,x,y,k); 88 } else printf("%lld\n",Query(1,x,y)); 89 } 90 91 return 0; 92 93 }
額開頭那個氧氣優化別在乎哈~
這個東西嘛
跟線段樹很像的
就是用一個lowbit瞎**搞
而後利用logn的時間求出來
這裏放一個題目:戳我
代碼以下qwq
1 #include <bits/stdc++.h> 2 3 using namespace std ; 4 5 const int MAXN = 500010; 6 int n,m; 7 int a[MAXN]; 8 int c[MAXN]; 9 10 inline void read(int &x) { 11 int num = 0 , negative = 0; 12 char ch = getchar(); 13 14 while((ch < '0' || ch > '9') && ch != '-') 15 ch = getchar(); 16 17 if(ch == '-') negative = 1; 18 else num = ch - '0'; 19 20 ch = getchar(); 21 22 while(ch >= '0' && ch <= '9') { 23 num = num * 10 + ch - '0'; 24 ch = getchar(); 25 } 26 27 x = num; 28 if(negative) 29 x = -x; 30 } 31 32 inline int lowbit(int x) { 33 return x & (-x); 34 } 35 36 inline int sum(int x) { 37 int ans = 0; 38 for(int i=x; i>0; i-=lowbit(i)) 39 ans += c[i]; 40 return ans; 41 } 42 43 inline void add(int x , int y) { 44 for(int i=x; i<=n; i+=lowbit(i)) 45 c[i] += y; 46 } 47 48 int main() { 49 50 read(n) , read(m); 51 for(int i=1; i<=n; i++) { 52 read(a[i]); 53 add(i,a[i]); 54 } 55 56 for(int i=1,z,x,y; i<=m; i++) { 57 read(z) , read(x) , read(y); 58 if(z == 1) add(x,y); 59 if(z == 2) printf("%d\n",sum(y) - sum(x-1)); 60 } 61 62 return 0; 63 64 }
講個笑話,樹狀數組的題都能用線段樹短
那爲何咱們還要樹狀數組呢?
固然是由於代碼短、更好寫了啦~
例題:戳我
LCA 是什麼意思呢 Largest China Apple?
哦哦哦哦哦不對固然不是這樣
求出最近公共祖先有什麼tarjan算法,還要什麼病茶几and check
本蒟蒻這裏就不介紹了,這裏介紹一個倍增的算法
倍增呢,是一個神奇的東西,就是把2^p化成2^(p-1) + 2^(p-1)
而後瞎**搞啦!
附上代碼
1 // luogu-judger-enable-o2 2 #include <iostream> 3 #include <cstdio> 4 #include <cmath> 5 6 using namespace std; 7 8 const int Maxn = 500010; 9 int n , m , s , tot , maxdep; 10 int last[Maxn]; 11 int depth[Maxn]; /* depth[i] : i的深度 */ 12 int f[Maxn][20]; /* f[i][k] : i的第2^k祖先 */ 13 14 struct Edge { 15 int to; 16 int next; 17 } e[Maxn*2]; 18 19 inline void add(int u , int v) { 20 tot ++; 21 e[tot].to = v; 22 e[tot].next = last[u]; 23 last[u] = tot; 24 } 25 26 inline void dfs(int x , int fa) { 27 28 depth[x] = depth[fa] + 1; 29 maxdep = max(maxdep,depth[x]); 30 f[x][0] = fa; 31 32 for(register int i=1; (1<<i)<=depth[x]; i++) 33 f[x][i] = f[f[x][i-1]][i-1]; 34 /* x的第2^k祖先 = x的第2^(k-1)祖先的第2^(k-1)祖先 */ 35 36 for(register int i=last[x]; i; i=e[i].next) { 37 register int y = e[i].to; 38 if(y != fa) dfs(y,x); /* 遍歷兒子 */ 39 } 40 41 } 42 43 inline int lca(int a , int b) { 44 45 if(a == b) return a; 46 if(depth[a] > depth[b]) swap(a,b); 47 48 for(register int i=maxdep; i>=0; i--) 49 if(depth[a] <= depth[b] - (1<<i)) 50 b = f[b][i]; 51 /* 一個數必定會由2^k+2^m+2^p+...組成 52 a的深度和b的深度的差距也必定會由2^k+2^m+2^p+...組成 53 因此最終必定會到同一層 */ 54 55 if(a == b) return a; 56 57 for(register int i=maxdep; i>=0; i--) { 58 if(f[a][i] == f[b][i]) continue; /* continue的做用是找a和b的最近祖先 */ 59 else a = f[a][i] , b = f[b][i]; 60 } 61 62 return f[a][0]; 63 64 } 65 66 int main() { 67 68 scanf("%d%d%d",&n,&m,&s); 69 for(register int i=1,x,y; i<n; i++) { 70 scanf("%d%d",&x,&y); 71 add(x,y); 72 add(y,x); 73 } 74 75 dfs(s,0); 76 77 maxdep = log2(maxdep); 78 for(register int u,v; m--; ) { 79 scanf("%d%d",&u,&v); 80 printf("%d\n",lca(u,v)); 81 } 82 83 return 0; 84 85 }
這裏插一句,集訓的時候咱們去了上海交♂大和上海鈕釦大學啊呸
而後身份證丟了……爲何呢?無可奉告。
最後仍是感謝海亮的老師們,幫我各類聯繫找到了身份證
就不用用半條命換錢包了
數論固然不是一個算法啦
當時就是萬惡的數論害的我……哇嗚嗚嗚嗚不說了
這裏說個exgcd,擴展歐幾里得算法
證實能夠說是能用幾個詞來形容了
就是 naive 顯而易見 易證 輕鬆的獲得了啦
啊呸啊呸我都說了什麼
好了 我搞個板子下來 湊個字數啦~
1 template < typename Typ > 2 inline Typ exgcd(Typ a , Typ b , Typ &x , Typ &y) { 3 4 if(!b) { 5 x = (Typ)1; 6 y = (Typ)0; 7 return a; 8 } 9 10 register Typ Gcd = exgcd(b,a%b,x,y); 11 12 register Typ tmp = x; 13 x = y; 14 y = tmp - a / b * y; 15 16 return Gcd; 17 18 }
template那一行是什麼意思呢?
一站式知足:戳我
沒想到吧 ->此處省略邪笑
簡稱馬拉車和看*片
你什麼都沒聽到qwq
這兩個算法是我見過的很玄學的算法
已經懶了,因此有代碼qwq
先是馬拉車
1 // luogu-judger-enable-o2 2 #include <iostream> 3 #include <cstring> 4 #include <cstdio> 5 6 const int Maxn = 11000010; 7 char s[Maxn]; 8 int pal[2*Maxn]; 9 10 inline void read() { 11 12 register int len = -1; 13 register char ch = getchar(); 14 15 while(ch != EOF) { 16 s[++len] = ch; 17 ch = getchar(); 18 } 19 20 } 21 22 int main() { 23 24 read(); 25 26 register int len = strlen(s); 27 28 register int l = -1 , r = -1 , ans = 0; 29 30 for(register int z=0; z<2*len; z++) { 31 register int i = ( z + 1 ) >> 1; 32 register int j = z >> 1; 33 register int p = 0; 34 if(i < r) p = std :: min(r-i,pal[2*(l+r)-z]); 35 while(j+p+1 < len && i-p-1 >= 0 && s[j+p+1] == s[i-p-1]) p ++; 36 if (j + p > r) { 37 r = j + p; 38 l = i - p; 39 } 40 pal[z] = p; 41 register int tmp = 2 * p + 1; 42 if( z & 1 ) tmp --; 43 ans = std :: max(ans,tmp); 44 } 45 46 printf("%d\n",ans); 47 48 return 0; 49 50 }
而後看*片
1 // luogu-judger-enable-o2 2 #include <iostream> 3 #include <cstdio> 4 5 using namespace std; 6 7 const int Maxn = 1000010; 8 int len1 , len2; 9 string x , y , a , b; 10 int next[Maxn]; 11 12 int main() { 13 14 cin >> a >> b; 15 16 len1 = a.size(); 17 len2 = b.size(); 18 19 x.resize(len1); 20 y.resize(len2); 21 22 for(register int i=1; i<=len1; i++) x[i] = a[i-1]; 23 for(register int i=1; i<=len2; i++) y[i] = b[i-1]; 24 25 next[1] = 0; 26 27 for(register int i=2,j=0; i<=len2; i++) { 28 while(j && y[i] != y[j+1]) j = next[j]; 29 if(y[i] == y[j+1]) j ++; 30 next[i] = j; 31 } 32 33 for(register int i=1,j=0; i<=len1; i++) { 34 while(j && x[i] != y[j+1]) j = next[j]; 35 if(x[i] == y[j+1]) j ++; 36 if(j == len2) { 37 printf("%d\n",i-len2+1); 38 j = next[j]; 39 } 40 } 41 42 for(register int i=1; i<=len2; i++) 43 printf("%d ",next[i]); 44 putchar('\n'); 45 46 return 0; 47 48 }
wow~我湊了好多字啦
啊呸啊呸沒什麼
下面講一個很是容易理解的字符串算法
猜猜看是什麼?
簡單介紹下,就是把字符串每一個字符弄成個子節點,而後暴力遍歷一遍就好了
模板題:戳我
沒想到吧!題目名稱這麼怪
我又要想個藉口貼模板啦!嗯就是這題比較簡單
因而上~模~板~
1 // luogu-judger-enable-o2 2 #include <iostream> 3 #include <cstring> 4 #include <cstdio> 5 6 using namespace std; 7 8 const int Maxn = 10010; 9 const int Son = 30; 10 int n , m , num; 11 struct Trie { 12 bool flag; 13 bool first; 14 int son[Son]; 15 } t[Maxn*50]; 16 17 inline void insert(string s) { 18 19 register int u = 0; 20 register int len = s.size(); 21 22 for(register int i=0; i<len; i++) { 23 register int v = int ( s[i] - 'a' + 1 ); 24 if(!t[u].son[v]) t[u].son[v] = ++ num; 25 u = t[u].son[v]; 26 } 27 28 t[u].flag = true; 29 30 } 31 32 inline int query(string s) { 33 34 register int u = 0; 35 register int len = s.size(); 36 register int state = 0; 37 38 for(register int i=0; i<len; i++) { 39 register int v = int ( s[i] - 'a' + 1 ); 40 if(!t[u].son[v]) return 1; 41 u = t[u].son[v]; 42 } 43 44 if(!t[u].flag) return 1; 45 if(t[u].first) return 2; 46 t[u].first = true; 47 return 0; 48 49 } 50 51 int main() { 52 53 register string name; 54 55 scanf("%d",&n); 56 for(register int i=1; i<=n; i++) { 57 cin >> name; 58 insert(name); 59 } 60 scanf("%d",&m); 61 for(; m--; ) { 62 cin >> name; 63 register int state = query(name); 64 if(!state) puts("OK"); 65 else if(state == 1) puts("WRONG"); 66 else puts("REPEAT"); 67 } 68 69 return 0; 70 71 }
這個算法很神奇,只要交上去就會自動A題,分分鐘成爲Rank1,媽媽不再用擔憂個人OI生活啦
等下。。。看錯算法了,那個算法是自動AC機QWQ
這個算法呢,就是要你熟練的掌握看*片算法和Trie樹
而後結合起來跑一遍就好了
有2道模板題:
不用說的啦~先附上代碼~
簡單版:
1 // luogu-judger-enable-o2 2 #include <iostream> 3 #include <cstdio> 4 #include <queue> 5 6 using namespace std; 7 8 const int Maxn = 1000010; 9 const int Maxm = 30; 10 int n , cnt; 11 12 struct Trie { 13 int fail; 14 int end; 15 int num[Maxm]; 16 } t[Maxn]; 17 18 inline void Build(string s) { 19 20 register int len = s.size(); 21 register int now = 0; 22 23 for(register int i=0; i<len; i++) { 24 register int to = s[i] - 'a' + 1; 25 if(!t[now].num[to]) t[now].num[to] = ++ cnt; 26 now = t[now].num[to]; 27 } 28 29 t[now].end ++; 30 31 } 32 33 inline void Getfail() { 34 35 queue <int> Q; 36 37 for(register int i=1; i<=26; i++) { 38 if(t[0].num[i]) { 39 t[t[0].num[i]].fail = 0; 40 Q.push(t[0].num[i]); 41 } 42 } 43 44 while(!Q.empty()) { 45 register int now = Q.front(); 46 Q.pop(); 47 for(register int i=1; i<=26; i++) { 48 if(t[now].num[i]) { 49 t[t[now].num[i]].fail = t[t[now].fail].num[i]; 50 Q.push(t[now].num[i]); 51 } else t[now].num[i] = t[t[now].fail].num[i]; 52 } 53 } 54 55 } 56 57 inline int Query(string s) { 58 59 register int len = s.size(); 60 register int now = 0 , ans = 0; 61 62 for(register int i=0; i<len; i++) { 63 register int to = s[i] - 'a' + 1; 64 now = t[now].num[to]; 65 for(register int j=now; j&&t[j].end; j=t[j].fail) { 66 ans += t[j].end; 67 t[j].end = 0; 68 } 69 } 70 71 return ans; 72 73 } 74 75 int main() { 76 77 register string s; 78 79 scanf("%d",&n); 80 for(register int i=1; i<=n; i++) { 81 cin >> s; 82 Build(s); 83 } 84 85 t[0].fail = 0; 86 87 Getfail(); 88 89 cin >> s; 90 91 cout << Query(s) << endl; 92 93 return 0; 94 95 }
吐槽一句luogu數據貌似有點水嗯哼
如今來提升版:
1 #include <algorithm> 2 #include <iostream> 3 #include <cstring> 4 #include <cstdio> 5 #include <queue> 6 7 using namespace std; 8 9 const int Maxn = 100010; 10 const int Maxm = 30; 11 int n , cnt; 12 string s[Maxn]; 13 queue <int> Q; 14 15 struct Trie { 16 int fail; 17 int end; 18 int num[Maxm]; 19 } t[Maxn]; 20 21 struct Str { 22 int id; 23 int tot; 24 } a[Maxn]; 25 26 inline void Clean(int x) { 27 28 t[x].end = t[x].fail = 0; 29 for(register int i=1; i<=26; i++) 30 t[x].num[i] = 0; 31 32 } 33 34 inline bool comp(const Str &x , const Str &y) { 35 if(x.tot > y.tot) return true; 36 if(x.tot < y.tot) return false; 37 return x.id < y.id; 38 } 39 40 inline void Build(string s , int idx) { 41 42 register int len = s.size(); 43 register int now = 0; 44 45 for(register int i=0; i<len; i++) { 46 register int to = s[i] - 'a' + 1; 47 if(!t[now].num[to]) { 48 t[now].num[to] = ++ cnt; 49 Clean(cnt); 50 } 51 now = t[now].num[to]; 52 } 53 54 t[now].end = idx; 55 56 } 57 58 inline void Getfail() { 59 60 while(!Q.empty()) Q.pop(); 61 62 for(register int i=1; i<=26; i++) { 63 if(t[0].num[i]) { 64 t[t[0].num[i]].fail = 0; 65 Q.push(t[0].num[i]); 66 } 67 } 68 69 while(!Q.empty()) { 70 register int now = Q.front(); 71 Q.pop(); 72 for(register int i=1; i<=26; i++) { 73 if(t[now].num[i]) { 74 t[t[now].num[i]].fail = t[t[now].fail].num[i]; 75 Q.push(t[now].num[i]); 76 } else t[now].num[i] = t[t[now].fail].num[i]; 77 } 78 } 79 80 } 81 82 inline void Query(string s) { 83 84 register int len = s.size(); 85 register int now = 0; 86 87 for(register int i=0; i<len; i++) { 88 register int to = s[i] - 'a' + 1; 89 now = t[now].num[to]; 90 for(register int j=now; j; j=t[j].fail) 91 a[t[j].end].tot ++; 92 } 93 94 } 95 96 int main() { 97 98 while(scanf("%d",&n) != EOF) { 99 100 if(!n) return 0; 101 102 cnt = 0; 103 Clean(0); 104 105 for(register int i=1; i<=n; i++) { 106 cin >> s[i]; 107 a[i].id = i; 108 a[i].tot = 0; 109 Build(s[i],i); 110 } 111 112 Getfail(); 113 114 cin >> s[0]; 115 Query(s[0]); 116 117 sort(a+1,a+n+1,comp); 118 119 printf("%d\n",a[1].tot); 120 cout << s[a[1].id] << endl; 121 for(register int i=2; i<=n; i++) { 122 if(a[i].tot != a[i-1].tot) break; 123 cout << s[a[i].id] << endl; 124 } 125 126 } 127 128 return 0; 129 130 }
其實提升版不難,加個排序等奇奇gaygay的操做就好了QVQ
哦對了,這些字符串算法全是一個dalao講的
在這裏我要瘋狂%%%%%%%飛神
我能記起來的最後一個算法:
差分約束
其實這個就是個轉成SPFA的算法
利用三角形不等式,dis[i] + e[i].w < dis[j] 而後……
還有各類判環就好了啦~so~easy~
模板題:戳我
附上代碼~
1 #include <iostream> 2 #include <cstdio> 3 #include <queue> 4 5 using namespace std; 6 7 typedef long long ll; 8 const int Maxn = 100010; 9 int n , m , tot; 10 int repeat[Maxn]; 11 int last[Maxn]; 12 int dis[Maxn]; 13 bool vis[Maxn]; 14 15 struct Edge { 16 int to; 17 int w; 18 int next; 19 } e[(Maxn<<1)+Maxn]; 20 21 queue < int > Q; 22 23 template < typename Typ > 24 inline void read(Typ &x) { 25 26 register Typ num = 0; 27 register char ch = getchar(); 28 29 while(ch < '0' || ch > '9') ch = getchar(); 30 31 while(ch >= '0' && ch <= '9') { 32 num = ( num << 3 ) + ( num << 1 ) + ch - '0'; 33 ch = getchar(); 34 } 35 36 x = num; 37 38 } 39 40 inline void add(int u , int v , int w) { 41 tot ++; 42 e[tot].to = v; 43 e[tot].w = w; 44 e[tot].next = last[u]; 45 last[u] = tot; 46 } 47 48 inline bool Spfa(int s) { 49 50 while(!Q.empty()) Q.pop(); 51 vis[s] = true; 52 Q.push(s); 53 54 while(!Q.empty()) { 55 register int u = Q.front(); 56 Q.pop(); 57 vis[u] = false; 58 for(register int i=last[u]; i; i=e[i].next) { 59 register int v = e[i].to; 60 if(dis[u] + e[i].w > dis[v]) { 61 repeat[v] ++; 62 if(repeat[v] >= n) return false; 63 dis[v] = dis[u] + e[i].w; 64 if(!vis[v]) { 65 vis[v] = true; 66 Q.push(v); 67 } 68 } 69 } 70 } 71 72 return true; 73 74 } 75 76 inline ll getsum() { 77 78 register ll sum = 0; 79 80 for(register int i=1; i<=n; i++) 81 sum += dis[i]; 82 83 return sum; 84 85 } 86 87 int main() { 88 89 read(n) , read(m); 90 for(register int x,y,z; m--; ) { 91 read(z) , read(x) , read(y); 92 if(z == 1) add(x,y,0) , add(y,x,0); 93 if(z == 2) { 94 if(x == y) return !puts("-1"); 95 add(x,y,1); 96 } 97 if(z == 3) add(y,x,0); 98 if(z == 4) { 99 if(x == y) return !puts("-1"); 100 add(y,x,1); 101 } 102 if(z == 5) add(x,y,0); 103 } 104 105 for(register int i=n; i>=1; i--) 106 add(0,i,1); 107 108 register bool tmp = Spfa(0); 109 if(!tmp) puts("-1"); 110 else printf("%lld\n",getsum()); 111 112 return 0; 113 114 }
好了~
我以爲總結好了呢~
但是並無呢~
等到集訓結束後咱們再見面吧~
By BlueCat