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++;
}
else
cout<<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(); //开始跑spfa
cout<<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(); //开始跑spfa
if(mp[end]==0||dis[mp[end]]==inf)
cout<<"-1"<<endl;
else cout<<dis[mp[end]]<<endl; //否则打印最短距离
}
return 0;
}