一起开心2020暑假训练第二周 图论(模板题)
生活随笔
收集整理的這篇文章主要介紹了
一起开心2020暑假训练第二周 图论(模板题)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
比賽鏈接:
文章目錄
- A HDU 1285 一
- B HDU 1863 起
- C POJ 2387 開
- D POJ 1502 心
- E HDU 5922 圖
- F HDU 2112 論
A HDU 1285 一
拓撲排序模板題,記錄每個點的入度,然后按照入度大小以及順序進行輸出
#include<iostream> #include<queue> #include<cstdio> #include<cstring> using namespace std; bool map[517][517]; int in[517]; priority_queue<int,vector<int>,greater<int> > q; void topo(int n) {for(int i=1;i<=n;i++){if(in[i]==0)q.push(i);}int c=1;while(!q.empty()){int v=q.top();q.pop();if(c!=n){cout<<v<<" ";c++;}elsecout<<v<<endl;for(int i=1;i<=n;i++){if(!map[v][i])continue;in[i]--;if(!in[i])q.push(i);}} } int main() {int n,m,i,j;while(cin>>n>>m){int k=0;memset(map,0,sizeof map);memset(in,0,sizeof in);while(m--){cin>>i>>j;if(map[i][j])continue;map[i][j]=1;in[j]++;}topo(n);} }B HDU 1863 起
最小生成樹模板題
#include<bits/stdc++.h> using namespace std; int n,m; const int maxn=1e6+32; struct node{int u,v,w; }edge[maxn]; int fa[maxn]; int total=0; bool cmp(node x,node y) {return x.w<y.w; } int sum=0; int find(int x) {if(fa[x]==x)return x;else return find(fa[x]); } inline void Kruskal() {total=0;sum=0;for(int i=1;i<=m;i++){int u=find(edge[i].u);int v=find(edge[i].v);if(u==v)continue;sum+=edge[i].w;fa[u]=v;total++;if(total==n-1)break;}} int main() {while(cin>>m>>n){if(m==0)break;for(int i=1;i<=n;i++)fa[i]=i;memset(edge,0,sizeof(edge));for(int i=1;i<=m;i++){cin>>edge[i].u>>edge[i].v>>edge[i].w;}sort(edge+1,edge+1+m,cmp);Kruskal();if(total==n-1)cout<<sum<<endl;else cout<<"?"<<endl;}return 0; }C POJ 2387 開
最短路模板,從n 到 1
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<queue> const long long inf=2147483647; const int maxn=10005; const int maxm=500005; using namespace std; int n,m,s,num_edge=0; int dis[maxn],vis[maxn],head[maxm]; struct Edge {int next,to,dis; }edge[maxm]; //結構體表示靜態鄰接表 void addedge(int from,int to,int dis) //鄰接表建圖 { //以下是數據結構書上的標準代碼,不懂翻書看解釋edge[++num_edge].next=head[from]; //鏈式存儲下一條出邊edge[num_edge].to=to; //當前節點編號edge[num_edge].dis=dis; //本條邊的距離head[from]=num_edge; //記錄下一次的出邊情況 } void spfa() {queue<int> q; //spfa用隊列,這里用了STL的標準隊列for(int i=1; i<=n; i++) {dis[i]=inf; //帶權圖初始化vis[i]=0; //記錄點i是否在隊列中,同dijkstra算法中的visited數組}q.push(s); dis[s]=0; vis[s]=1; //第一個頂點入隊,進行標記while(!q.empty()){int u=q.front(); //取出隊首q.pop(); vis[u]=0; //出隊標記for(int i=head[u]; i; i=edge[i].next) //鄰接表遍歷,不多解釋了(也可用vector代替){int v=edge[i].to; if(dis[v]>dis[u]+edge[i].dis) //如果有最短路就更改{dis[v]=dis[u]+edge[i].dis;if(vis[v]==0) //未入隊則入隊{vis[v]=1; //標記入隊q.push(v);}}}} } int main() {cin>>m>>n;s=n;for(int i=1; i<=m; i++){int f,g,w;cin>>f>>g>>w; addedge(f,g,w); //建圖,有向圖連一次邊就可以了addedge(g,f,w);}spfa(); //開始跑spfacout<<dis[1]<<endl; //否則打印最短距離return 0; }D POJ 1502 心
也是最短路模板題,只是讀入方式有些奇怪
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<algorithm>#define inf 0x7f using namespace std; const int MAXN=10010,MAXM=500010;struct XY{int w,to,pre; }e[MAXM];struct XX{int dis,num; }d[MAXN],tmp;struct cmp1{bool operator ()(XX &a,XX &b){return a.dis>b.dis;} }; char w[110]; int n,s,sz=0; int las[100010]; bool flag[MAXN]; priority_queue<XX,vector<XX>,cmp1> q;void init() {sz=0;memset(las,0,sizeof(las));memset(flag,0,sizeof(flag)); } void add(int x,int y,int w){++sz;e[sz].to=y;e[sz].w=w;e[sz].pre=las[x];las[x]=sz; }void Dijkstra(){int min,u=0;s=1;d[s].dis=0;q.push(d[s]);while (!q.empty()){u=q.top().num;q.pop();if (flag[u]) continue;flag[u]=true;for (int j=las[u];j;j=e[j].pre){int mu=e[j].to;if (d[mu].dis>d[u].dis+e[j].w){d[mu].dis=d[u].dis+e[j].w;q.push(d[mu]);}}} }int zhuanhua(char s[]) {if(s[0]=='x')return inf;else{int sum=0;for(int i=0; i<strlen(s); i++)sum=sum*10+s[i]-'0';return sum;} }int main(){while(scanf("%d",&n)!=EOF){init();memset(e,0,sizeof(e));for (int i=1;i<=n;++i){d[i].num=i;d[i].dis=2147483647;}for(int i=2;i<=n;i++){for(int j=1;j<i;j++){scanf("%s",w);int zz=zhuanhua(w);add(i,j,zz);add(j,i,zz);}}Dijkstra();int maxx=0;for (int i=1;i<=n;++i)maxx=max(maxx,d[i].dis);cout <<maxx;while(!q.empty())q.pop(); }return 0; }E HDU 5922 圖
找規律,表面是最小生成樹,但仔細看會發現將點1與其他點相連費用最低(因為費用為兩點之和,而1是最小的數)
#include<iostream> using namespace std; typedef long long ll; int main() {int t;cin>>t;for(int i=1;i<=t;i++){ll n;cin>>n;printf("Case #%d: %lld\n",i,(n-1)*(n+2)/2);} }F HDU 2112 論
也是最短路,不過每個站點都是具體的城市名,可以用map實現名字與編號的唯一對應
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<map> #include<queue> const long long inf=2147483647; const int maxn=30005; const int maxm=70005; using namespace std; int n,m,s,num_edge=0; map<string,int>mp; int dis[maxn],vis[maxn],head[maxm]; struct Edge {int next,to,dis; }edge[maxm]; //結構體表示靜態鄰接表 void addedge(int from,int to,int dis) //鄰接表建圖 { //以下是數據結構書上的標準代碼,不懂翻書看解釋edge[++num_edge].next=head[from]; //鏈式存儲下一條出邊edge[num_edge].to=to; //當前節點編號edge[num_edge].dis=dis; //本條邊的距離head[from]=num_edge; //記錄下一次的出邊情況 } void spfa() {queue<int> q; //spfa用隊列,這里用了STL的標準隊列for(int i=1; i<=n; i++) {dis[i]=inf; //帶權圖初始化vis[i]=0; //記錄點i是否在隊列中,同dijkstra算法中的visited數組}q.push(s); dis[s]=0; vis[s]=1; //第一個頂點入隊,進行標記while(!q.empty()){int u=q.front(); //取出隊首q.pop(); vis[u]=0; //出隊標記for(int i=head[u]; i; i=edge[i].next) //鄰接表遍歷,不多解釋了(也可用vector代替){int v=edge[i].to; if(dis[v]>dis[u]+edge[i].dis) //如果有最短路就更改{dis[v]=dis[u]+edge[i].dis;if(vis[v]==0) //未入隊則入隊{vis[v]=1; //標記入隊q.push(v);}}}} } void init() {num_edge=0;mp.erase(mp.begin(),mp.end());memset(head,0,sizeof(head));memset(edge,0,sizeof(edge));} int main() {while(cin>>m){init();if(m==-1)break;string a,end,b;cin>>a>>end;mp[a]=1;s=1;int cnt=1;for(int i=1; i<=m; i++){int w;cin>>a>>b>>w;if(mp[a]==0)mp[a]=++cnt;if(mp[b]==0)mp[b]=++cnt; addedge(mp[a],mp[b],w); //建圖,有向圖連一次邊就可以了addedge(mp[b],mp[a],w);}n=cnt;spfa(); //開始跑spfaif(mp[end]==0||dis[mp[end]]==inf)cout<<"-1"<<endl;else cout<<dis[mp[end]]<<endl; //否則打印最短距離}return 0; }總結
以上是生活随笔為你收集整理的一起开心2020暑假训练第二周 图论(模板题)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 详解香港主机和国内主机的区别
- 下一篇: 2020牛客暑期多校训练营(第二场)