标签:break 常用 noi 后缀 电脑 struct 之间 add stream
1 void dfs(int now) 2 { 3 deep[now]=deep[fa[now]]+1; 4 sum[now]=value[now]; maxx[now]=value[now]; 5 for 遍历从now出发的每一条边,边到达的点是v 6 if (v != fa[now]) 7 { 8 fa[v]=now; 9 dfs(v); 10 sum[now]+=sum[v]; maxx[now]=max(maxx[now], maxx[v]); 11 } 12 }
struct Edge_tree{ int u,v,w; int next; }; Edge_tree edge[maxn]; int cnt = 0; int first[maxn]; void add_edge(int from,int to,int dis){ edge[++cnt].u = from; edge[cnt].v = to; edge[cnt].w = dis; edge[cnt].next = fisrt[from]; first[from] =cnt; /* 作为一棵无向树,还需要反向进行加边操作。 图的邻接表不也是这样吗? */ edge[++cnt].v = from; edge[cnt].u = to; edge[cnt].w = dis; edge[cnt].next = first[to]; first[to] = cnt; /* 这超酷,是不是? 以前我还从来没有想过可以使用邻接表存一棵树! 这可以说是最新操作了。 */ } void dfs_tree(int x,int fa){ //cout << x << " "; for (int i = first[x];i!=0;i = edge[i].next) if (edge[i].v != fa) dfs_tree(edge[i].v,x); }
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<vector> 5 #define maxn 2333 6 using namespace std; 7 int f[maxn][maxn]; 8 int father[maxn]; 9 int deep[maxn]; 10 vector<int> tree; 11 12 void dfs(int x){ 13 f[x][0] = father[x]; 14 for (int i=1;i<=n;i++) 15 f[x][i] = f[f[x][i-1]][i-1]; 16 for (int i=0;i<tree[x].size();i++){ 17 if (tree[x][i]!=father[x]){ 18 int y = tree[x][i]; 19 father[y] = x; 20 deep[y] = deep[x]+1; 21 dfs(y); 22 } 23 } 24 }//从根节点开始dfs,预处理f数组 25 26 //查询LCA: 27 int lca(int x,int y){ 28 if (deep[x]<deep[y]) 29 swap(x,y); 30 for (int i=n;i>=0;i--) 31 if (deep[y] <= deep[f[x][i]]) 32 x = f[x][i]; 33 if (x==y) 34 return x; 35 for (int i=n;i>=0;i--) 36 if (f[x][i]!=f[y][i]){ 37 x = f[x][i]; 38 y = f[y][i]; 39 } 40 return f[x][0]; 41 } 42 43 int main(){ 44 //do something 45 return 0; 46 }
1 struct Edge{ 2 long long int from,to,dis; 3 }; 4 Edge edge[maxn]; 5 long long int head[maxn]; 6 long long int cnt = 0; 7 void add_edge(long long int from,long long int to,long long int dis){ 8 edge[++cnt].from = head[from]; 9 edge[cnt].to = to; 10 edge[cnt].dis = dis; 11 head[from] = cnt; 12 }
这是我最常用的邻接表。开一个struct存边。
加边操作其实就是往链表里塞一个节点罢了。那个head数组表示第i个点连接的下一条边的编号。
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<queue> 5 #include<vector> 6 #include<algorithm> 7 #define ll long long 8 #define INF 2147483647 9 using namespace std; 10 int n,m,s,head[50010],cnt; 11 ll dis[10010]; 12 bool used[10010]; 13 struct Edge{ 14 int to,from,dis; 15 }edge[500010]; 16 17 void add_edge(int u,int v,int dis){ 18 edge[cnt].to=v; 19 edge[cnt].from=head[u]; 20 edge[cnt].dis=dis; 21 head[u]=cnt++; 22 } 23 typedef pair<int,int> P; 24 void dijkstra(int s){ 25 priority_queue<P,vector<P>,greater<P> > q; 26 fill(dis,dis+n+1,INF); 27 fill(used,used+n+1,false); 28 dis[s]=0; 29 q.push(P(0,s)); 30 while(!q.empty()){ 31 P p=q.top();q.pop(); 32 int u=p.second; 33 if(used[u]) continue; 34 used[u]=true; 35 int pp=head[u]; 36 while(pp!=-1){ 37 int v=edge[pp].to; 38 if(!used[v]&&dis[v]>dis[u]+edge[pp].dis){ 39 dis[v]=dis[u]+edge[pp].dis; 40 q.push(P(dis[v],v)); 41 } 42 pp=edge[pp].from; 43 } 44 } 45 } 46 int main(){ 47 memset(head,-1,sizeof(head)); 48 cin>>n>>m>>s; 49 for(int i=1;i<=m;i++){ 50 int u,v,d; 51 scanf("%d%d%d",&u,&v,&d); 52 add_edge(u,v,d); 53 } 54 dijkstra(s); 55 for(int i=1;i<=n;i++) printf("%lld ",dis[i]); 56 return 0; 57 }
用了一个pair,对组,用来存放最短路径
priority_queue<P,vector<P>,greater<P> > q;这样声明,便成了小根堆,我们每次都要取最小的边。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<queue> 5 #define maxn 5000015 6 #define INF 2147483647 7 #define ms(x) memset(x,0,sizeof(x)); 8 using namespace std; 9 struct Edge{ 10 long long int from,to,dis; 11 }; 12 Edge edge[maxn]; 13 long long int n,m,s,u,v,d; 14 long long int head[maxn]; 15 long long int dis[maxn]; 16 bool inq[maxn]; 17 long long int cnt = 0; 18 void add_edge(long long int from,long long int to,long long int dis){ 19 edge[++cnt].from = head[from]; 20 edge[cnt].to = to; 21 edge[cnt].dis = dis; 22 head[from] = cnt; 23 } 24 25 void spfa(void){ 26 queue<long long int> q; 27 q.push(s); 28 inq[s] = true; 29 ms(inq); 30 for (int i=1;i<=n;i++) 31 dis[i] = INF; 32 dis[s] = 0; 33 while (!q.empty()){ 34 long long int u = q.front(); 35 q.pop(); 36 inq[s] = false; 37 for (int i=head[u];i!=0;i=edge[i].from){ 38 long long int v = edge[i].to; 39 long long int w = edge[i].dis; 40 if (dis[u]+w < dis[v]){ 41 dis[v] = w+ dis[u]; 42 if (!inq[v]){ 43 q.push(v); 44 inq[v] = true; 45 } 46 } 47 } 48 } 49 50 } 51 52 int main(){ 53 cin >> n >> m >> s; 54 for (int i=1;i<=m;i++){ 55 cin >> u >> v >> d; 56 add_edge(u,v,d); 57 } 58 spfa(); 59 for (int i=1;i<=n;i++) 60 cout << dis[i] << " "; 61 return 0; 62 }
如果要判断负环的话,再加一个数组记录每个点入队的次数,如果在入队操作时发现一个点的入队次数超过n,则一定存在负环。
1 1.初始化 father[x] = [x],tot = 0 2 2.对所有边进行边权排序,设边数为m 3 3.for (int i=1;i<=m;i++){ 4 if 当前的这条边连接的两个点不属于同一集合{ 5 合并两集合,并把边(u,v)加入最小生成树 6 tot += w(u,v),k++ 7 if (k==n-1) 8 break; 9 } 10 }
标签:break 常用 noi 后缀 电脑 struct 之间 add stream
原文地址:http://www.cnblogs.com/OIerShawnZhou/p/7287408.html