比赛链接:
文章目录
- 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;
}