BZOJ.PA2009 Cakes(三元環)
思路:三元環的裸題。第一次寫還是稍微整理一下求三元環的思路。
1.無向圖(無重邊,無自環)轉化爲有向無環圖。
轉化的方法:對於任意邊度數大的結點指向度數小的結點,若度數相同,則編號小的結點指向編號大的結點。
用表達式即:
變爲有向邊。
2.接下來就是遍歷每個結點看能否形成三元環。
對於結點的所有相鄰結點打上標記,再對每個遍歷它的相鄰結點,若有給的標記,說明是一個三元環。
說明:這裏每個三元環只會被記錄一次。
時間複雜度:
簡單證明下時間複雜度:
顯然我們考慮一條邊對時間的貢獻是,
則總時間複雜度爲:
是結點的出度。
顯然分兩種情況。
當時,因爲,所以時間複雜度是。
當時,因爲圖的總度數是的,所以度數的結點至多有個,而只能連向度數不小於它的結點,所以時間複雜度:.
綜上:總時間複雜度:.
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5,M=1e6+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a) memset(a,0,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair<int,int>
#define fi first
#define se second
int n,m,deg[N],vis[N],val[N];
vector<int>e[N];
struct node{
int u,v;
}a[N];
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&val[i]);
for(int i=1;i<=m;i++){
int u,v;
scanf("%d%d",&u,&v);
deg[u]++,deg[v]++;
a[i]={u,v};
}
for(int i=1;i<=m;i++){
int u=a[i].u,v=a[i].v;
if(deg[u]>deg[v]||deg[u]==deg[v]&&u>v) swap(u,v); //無向圖轉有向無環圖.
e[u].push_back(v);
}
ll ans=0;
for(int i=1;i<=n;i++){
for(auto v:e[i]) vis[v]=i;
for(auto u:e[i])
for(auto v:e[u])
if(vis[v]==i) ans+=max({val[u],val[v],val[i]});
}
printf("%lld\n",ans);
return 0;
}