574B】Bear and Three Musketeers (列舉邊,思維,優秀暴力)
題幹:
Do you know a story about the three musketeers? Anyway, you will learn about its origins now.
Richelimakieu is a cardinal in the city of Bearis. He is tired of dealing with crime by himself. He needs three brave warriors to help him to fight against bad guys.
There are n warriors. Richelimakieu wants to choose three of them to become musketeers but it's not that easy. The most important condition is that musketeers must know each other to cooperate efficiently. And they shouldn't be too well known because they could be betrayed by old friends. For each musketeer his recognition is the number of warriors he knows, excluding other two musketeers.
Help Richelimakieu! Find if it is possible to choose three musketeers knowing each other, and what is minimum possible sum of their recognitions.
Input
The first line contains two space-separated integers, n and m (3 ≤ n ≤ 4000, 0 ≤ m ≤ 4000) — respectively number of warriors and number of pairs of warriors knowing each other.
i-th of the following m lines contains two space-separated integers ai and bi (1 ≤ ai, bi ≤ n, ai ≠ bi). Warriors ai and bi know each other. Each pair of warriors will be listed at most once.
Output
If Richelimakieu can choose three musketeers, print the minimum possible sum of their recognitions. Otherwise, print "-1" (without the quotes).
Examples
Input
5 6 1 2 1 3 2 3 2 4 3 4 4 5
Output
2
Input
7 4 2 1 3 6 5 1 1 7
Output
-1
Note
In the first sample Richelimakieu should choose a triple 1, 2, 3. The first musketeer doesn't know anyone except other two musketeers so his recognition is 0. The second musketeer has recognition 1 because he knows warrior number 4. The third musketeer also has recognition 1 because he knows warrior 4. Sum of recognitions is 0 + 1 + 1 = 2.
The other possible triple is 2, 3, 4 but it has greater sum of recognitions, equal to 1 + 1 + 1 = 3.
In the second sample there is no triple of warriors knowing each other.
解題報告:
顯然,2000ms的時限,4000的資料量,考慮是否o(n^2)可以解決。(其實這題直接列舉三個點,o(n^3)也可以過?)怎麼優化到平方級別呢?其實也很簡單,就是第一層迴圈遍歷m條邊就好了。因為你三層for列舉頂點的時候,其實前兩層有很多是浪費掉了的,因為有很多頂點的之間根本沒有邊,而你都遍歷了一遍,所以我們都記錄下來邊了,為什麼不直接遍歷邊呢?這樣我們就有兩個頂點了呀,然後再來一層迴圈遍歷每一個點就好了。注意這種暴力的題一定別忘判斷一下是否遍歷到了自己,比如【CodeForces - 761C】Dasha and Password 這道題,最開始就忘了判斷是否遍歷到了同一個字串。
AC程式碼:
#include<bits/stdc++.h>
using namespace std;
const int MAX = 4000 + 5 ;
int du[MAX];
bool maze[MAX][MAX];
int head[MAX];
struct Edge {
int fm,to;
int w;
}e[50000 + 5];
int top;
void add(int u,int v) {
e[++top].fm = u;
e[top].to = v;
}
int main()
{
int n,m,u,v;
cin>>n>>m;
for(int i = 1; i<=m; i++) {
scanf("%d%d",&u,&v);
add(u,v);add(v,u);
du[u]++;du[v]++;
maze[u][v] = maze[v][u] = 1;
}
int ans = 0x3f3f3f3f;
for(int i = 1; i<=top; i++) {
for(int j = 1; j<=n; j++) {
if(j == e[i].fm || j == e[i].to) continue;
if(maze[e[i].fm][j] && maze[e[i].to][j]) {
ans = min(ans,du[e[i].to] + du[e[i].fm] + du[j]);
}
}
}
if(ans == 0x3f3f3f3f) puts("-1");
else printf("%d\n",ans-6);
return 0 ;
}
AC程式碼2:(其實也不是拓撲排序啦,就是用vector表示了二維陣列,並且,由第二個點找第三個點的時候直接在第一個點所連的邊中找就可以了。但是那個c函式其實也有點消耗時間?如果直接用個bool型別的maze二維陣列來表示無向圖兩點之間是否相連就更快了)