publicclasstop_sort{//拓扑序列 staticint N = 100010; staticint[] e = newint[N]; staticint[] ne = newint[N]; staticint[] h = newint[N]; staticint[] q = newint[N]; staticint[] d = newint[N];//存入度 staticint idx = 1, n;
staticvoidadd(int a, int b){ e[idx] = b; ne[idx] = h[a]; h[a] = idx++; }
staticbooleantopSort(){ int tt = -1, hh = 0; for (int i = 1; i <= n; i++) {//让所有入度为0的节点入队 if (d[i] == 0) q[++tt] = i; } while (hh <= tt) { int t = q[hh++]; for (int i = h[t]; i != 0; i = ne[i]) { int j = e[i]; if (--d[j] == 0) q[++tt] = j;//入队 } } return tt == n - 1;//判断所有点是否都入队了->存在环则必有点入度始终不为0 }
publicstaticvoidmain(String[] args)throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String[] str = br.readLine().split(" "); n = Integer.parseInt(str[0]); int m = Integer.parseInt(str[1]); while (m-- != 0) { String[] s = br.readLine().split(" "); int a = Integer.parseInt(s[0]); int b = Integer.parseInt(s[1]); d[b]++;//b入度+1 add(a, b); } if (topSort()) { for (int i = 0; i < n; i++) System.out.print(q[i] + " "); System.out.println(); } else { System.out.println("-1"); } } }
publicclassMain{ staticint N = 510; staticint[][] g = newint[N][N];//稠密图使用邻接矩阵存储 staticint[] dist = newint[N]; staticboolean[] st = newboolean[N]; //相当于s集合,确定了和1号店的最短距离的点加入到s集合中 staticint n; staticint MAX = 0x3f3f3f3f;
staticintDijkstra(){ Arrays.fill(dist, MAX); dist[1] = 0; for (int i = 1; i <= n; i++) { //找到当前距离1号点最近的点t int t = -1; for (int j = 1; j <= n; j++) { if (!st[j] && (t == -1 || dist[t] > dist[j])) t = j; } st[t] = true; for (int j = 1; j <= n; j++) { dist[j] = Math.min(dist[j], dist[t] + g[t][j]); } } if(dist[n]==MAX)return -1; return dist[n]; }
publicstaticvoidmain(String[] args)throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String[] str = br.readLine().split(" "); n = Integer.parseInt(str[0]); int m = Integer.parseInt(str[1]);
//初始化g为正无穷,解决重边的问题 for (int i = 1; i <= n; i++) Arrays.fill(g[i], MAX);
while (m-- > 0) { String[] arr = br.readLine().split(" "); int a = Integer.parseInt(arr[0]); int b = Integer.parseInt(arr[1]); int c = Integer.parseInt(arr[2]); g[a][b] = Math.min(g[a][b], c); } System.out.println(Dijkstra()); }
publicclassdijkstra_heap{ staticint N = 150010; staticint n;
staticint[] h = newint[N]; staticint[] e = newint[N]; staticint[] ne = newint[N]; staticint[] w = newint[N]; staticint idx = 1; staticint[] dist = newint[N]; staticboolean[] st = newboolean[N]; staticint INF = 0x3f3f3f3f;
staticvoidadd(int a, int b, int c){ e[idx] = b; w[idx] = c; ne[idx] = h[a]; h[a] = idx++; }
staticintdijkstra(){ PriorityQueue<PII> queue = new PriorityQueue<>(); Arrays.fill(dist, INF); dist[1] = 0; queue.add(new PII(0, 1)); while (!queue.isEmpty()) { //1、找到当前未在s中出现过且离源点最近的点 PII p = queue.poll(); int distant = p.getDistant(); int t = p.getIndex(); if (st[t]) continue; //2、将该点进行标记 st[t] = true; //3、用t更新其他点的距离 for (int i = h[t]; i != 0; i = ne[i]) { int j = e[i]; if (dist[j] > distant + w[i]) { dist[j] = distant + w[i]; queue.add(new PII(dist[j], j)); } } } if (dist[n] == INF) return -1; return dist[n]; }
publicstaticvoidmain(String[] args)throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String[] str = br.readLine().split(" "); n = Integer.parseInt(str[0]); int m = Integer.parseInt(str[1]); while (m-- != 0) { String[] s = br.readLine().split(" "); int a = Integer.parseInt(s[0]); int b = Integer.parseInt(s[1]); int c = Integer.parseInt(s[2]); add(a, b, c); } System.out.println(dijkstra()); }
for (int i = 0; i < k; i++) { backup = Arrays.copyOf(dist, n + 1); for (int j = 0; j < m; j++) { int a = e[j].a; int b = e[j].b; int c = e[j].c; dist[b] = Math.min(dist[b], backup[a] + c);//用上面的点来更新后面的点 } } //因为到不了最后的n点,然后存在负权边能够到达n,将n的值更新了之后,变得比max小,防止出现这种情况 if (dist[n] > max / 2) System.out.println("impossible"); else System.out.println(dist[n]); }
publicstaticvoidmain(String[] args)throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String[] str = br.readLine().split(" "); n = Integer.parseInt(str[0]); m = Integer.parseInt(str[1]); k = Integer.parseInt(str[2]); for (int i = 0; i < m; i++) { String[] s = br.readLine().split(" "); int a = Integer.parseInt(s[0]); int b = Integer.parseInt(s[1]); int c = Integer.parseInt(s[2]); e[i] = new Edges(a, b, c); } bellmanFord(); }
}
spfa
通过队列来优化bellman的步骤: dist[b] = Math.min(dist[b], dist[a] + c)
//不存在负环 publicclassspfa{ staticint N = 100010; staticint[] e = newint[N]; staticint[] ne = newint[N]; staticint[] h = newint[N]; staticint[] dist = newint[N]; staticboolean[] st = newboolean[N]; staticint[] w = newint[N]; staticint idx = 1, n; staticint MAX = 0x3f3f3f3f;
staticvoidadd(int a, int b, int c){ e[idx] = b; w[idx] = c; ne[idx] = h[a]; h[a] = idx++; }
staticvoidSpfa(){ Queue<Integer> q = new LinkedList<>(); Arrays.fill(dist, MAX); dist[1] = 0; st[1] = true; q.offer(1); while(!q.isEmpty()){ int t = q.poll(); st[t] = false; //遍历这个点连接的所有边 for(int i = h[t]; i != 0; i = ne[i]){ int j = e[i]; //更新一下最短路 if(dist[j] > dist[t] + w[i]){ dist[j] = dist[t] + w[i]; //当前点被更新,加入队列 if(!st[j]){ q.offer(j); st[j] = true; } } } } if(dist[n] == MAX)System.out.println("impossible"); else System.out.println(dist[n]); }
publicstaticvoidmain(String[] args)throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String[] str = br.readLine().split(" "); n = Integer.parseInt(str[0]); int m = Integer.parseInt(str[1]); while (m-- != 0) { String[] s = br.readLine().split(" "); int a = Integer.parseInt(s[0]); int b = Integer.parseInt(s[1]); int c = Integer.parseInt(s[2]); add(a, b, c); } Spfa(); } }
//不存在负环 publicclassMain{ staticint N = 100010; staticint[] e = newint[N]; staticint[] ne = newint[N]; staticint[] h = newint[N]; staticint[] dist = newint[N]; staticboolean[] st = newboolean[N]; staticint[] w = newint[N]; staticint[] cnt = newint[N]; staticint idx = 1, n; staticint MAX = 0x3f3f3f3f;
staticvoidadd(int a, int b, int c){ e[idx] = b; w[idx] = c; ne[idx] = h[a]; h[a] = idx++; }
staticbooleanSpfa(){ Queue<Integer> q = new LinkedList<>(); //全部点入队这样就没有负环无法经过,题中没说是否是连通图 for(int i = 1; i <= n; i++){ st[i] = true; q.offer(i); } while(!q.isEmpty()){ int t = q.poll(); st[t] = false; //遍历这个点连接的所有边 for(int i = h[t]; i != 0; i = ne[i]){ int j = e[i]; //更新一下最短路 if(dist[j] > dist[t] + w[i]){ dist[j] = dist[t] + w[i]; //记录路径长度 cnt[j] = cnt[t] + 1; //如果长度大于等于n,说明走过n+1个点,说明走过负环 if(cnt[j] >= n)returntrue; //当前点被更新,加入队列 if(!st[j]){ q.offer(j); st[j] = true; } } } } returnfalse; }
publicstaticvoidmain(String[] args)throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String[] str = br.readLine().split(" "); n = Integer.parseInt(str[0]); int m = Integer.parseInt(str[1]); while (m-- != 0) { String[] s = br.readLine().split(" "); int a = Integer.parseInt(s[0]); int b = Integer.parseInt(s[1]); int c = Integer.parseInt(s[2]); add(a, b, c); } if(Spfa())System.out.println("Yes"); else System.out.println("No"); } }
publicstaticvoidmain(String[] args)throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String[] str = br.readLine().split(" "); n = Integer.parseInt(str[0]); int m = Integer.parseInt(str[1]); int k = Integer.parseInt(str[2]);
while(m-- != 0){ String[] s1 = br.readLine().split(" "); int x = Integer.parseInt(s1[0]); int y = Integer.parseInt(s1[1]); int z = Integer.parseInt(s1[2]); d[x][y] = Math.min(d[x][y], z);//重边取最小 } Floyd();
while(k-- != 0){ String[] s2 = br.readLine().split(" "); int a = Integer.parseInt(s2[0]); int b = Integer.parseInt(s2[1]); int t = d[a][b]; if(t > INF/2)System.out.println("impossible"); else System.out.println(t); } } }
//朴素prim算法(稠密图) publicclassprim{ staticint N = 510; //static int M = 100010;//m ~ n ^ 2 稠密图 staticint[] dist = newint[N]; staticboolean[] st = newboolean[N]; staticint[][] g = newint[N][N]; staticint INF = 0x3f3f3f3f; staticint n, m;
staticintPrim(){ Arrays.fill(dist, INF); int res = 0; dist[1] = 0; for (int i = 0; i < n; i++) { int t = -1; for (int j = 1; j <= n; j++) { if (!st[j] && (t == -1 || dist[t] > dist[j])) t = j; } //说明图不连通,无最小生成树 if (dist[t] == INF) return INF; //选出一条最小生成树的边,记录下来 res += dist[t]; st[t] = true; //更新其他点到集合的距离->已经在集合内的就不必再更新了防止捣乱 for (int j = 1; j <= n; j++) { if (!st[j]) dist[j] = Math.min(dist[j], g[t][j]); } } return res; }
publicstaticvoidmain(String[] args)throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String[] str = br.readLine().split(" "); n = Integer.parseInt(str[0]); m = Integer.parseInt(str[1]); for (int i = 1; i <= n; i++) Arrays.fill(g[i], INF); while (m-- != 0) { String[] s = br.readLine().split(" "); int a = Integer.parseInt(s[0]); int b = Integer.parseInt(s[1]); int c = Integer.parseInt(s[2]); g[a][b] = g[b][a] = Math.min(g[a][b], c);//无向图不要忘记 } int t = Prim(); if (t == INF) System.out.println("impossible"); else System.out.println(t); } }
staticintKruskal(){ Arrays.sort(e, 0, m);//0~m-1排序 for (int i = 1; i <= n; i++) p[i] = i; int res = 0;//记录权值之和 int cnt = 0;//记录边数 for (int i = 0; i < m; i++) { int a = e[i].a; int b = e[i].b; int w = e[i].w; a = find(a); b = find(b); if(a != b){ p[a] = b;//合并 res += w; cnt++; } } if(cnt < n - 1)return INF;//不连通 return res; }
publicstaticvoidmain(String[] args)throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String[] str = br.readLine().split(" "); n = Integer.parseInt(str[0]); m = Integer.parseInt(str[1]); for (int i = 0; i < m; i++) { String[] s = br.readLine().split(" "); int a = Integer.parseInt(s[0]); int b = Integer.parseInt(s[1]); int w = Integer.parseInt(s[2]); e[i] = new edge(a, b, w); } int t = Kruskal(); if (t == INF) System.out.println("impossible"); else System.out.println(t); } }
publicclasscolour{ staticint N = 100010; staticint M = 2 * N; staticint[] e = newint[M]; staticint[] ne = newint[M]; staticint[] h = newint[N]; staticint[] color = newint[N]; staticint idx = 1, n, m;
staticvoidadd(int a, int b){ e[idx] = b; ne[idx] = h[a]; h[a] = idx++; }
staticbooleandfs(int u, int c){ color[u] = c; for (int i = h[u]; i != 0; i = ne[i]) { int j = e[i]; if (color[j] == 0) {//未染色 if (!dfs(j, 3 - c))returnfalse; } elseif(color[j] == c)returnfalse;//矛盾 } returntrue; }
publicstaticvoidmain(String[] args)throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String[] str = br.readLine().split(" "); n = Integer.parseInt(str[0]); m = Integer.parseInt(str[1]); while (m-- != 0) { String[] s = br.readLine().split(" "); int a = Integer.parseInt(s[0]); int b = Integer.parseInt(s[1]); add(a, b); add(b, a); } boolean flag = true; for (int i = 1; i <= n; i++) { if (color[i] == 0) if (!dfs(i, 1)) { flag = false; break; } } if (flag) System.out.println("Yes"); else System.out.println("No"); } }
publicclassxiongyali{ staticint N = 505; staticint M = 100010; staticint[] e = newint[M]; staticint[] ne = newint[M]; staticint[] h = newint[N]; staticint[] match = newint[N];//match是表示女生对应的男生是谁 staticboolean[] st = newboolean[N]; staticint idx = 1, n1, n2;
staticvoidadd(int a, int b){ e[idx] = b; ne[idx] = h[a]; h[a] = idx++; }
staticbooleanfind(int x){ //每一次遍历一遍传进来的左边集合x对应的右边集合中的点 for (int i = h[x]; i != 0; i = ne[i]) { int j = e[i]; // 判断这个点是不是已经用过了,没用过继续 if (!st[j]) { st[j] = true;//递归判重防止死循环 //女生还没被匹配或者谦让的美德起了作用 if (match[j] == 0 || find(match[j])) { match[j] = x; returntrue; } } } returnfalse; }
publicstaticvoidmain(String[] args)throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String[] str = br.readLine().split(" "); n1 = Integer.parseInt(str[0]); n2 = Integer.parseInt(str[1]); int m = Integer.parseInt(str[2]); while (m-- != 0) { String[] s = br.readLine().split(" "); int a = Integer.parseInt(s[0]); int b = Integer.parseInt(s[1]); add(a, b); } int res = 0; for (int i = 1; i <= n1; i++) { //每一次模拟都要将st数组清空,这个判断重复的点,match是物有所主了 //st数组用来保证本次匹配过程中,右边集合中的每个点只被遍历一次,防止死循环 //match存的是右边集合中的每个点当前匹配的点是哪个,但就算某个点当前已经匹配了某个点 //也有可能被再次遍历,所以不能起到判重的作用 Arrays.fill(st, false); if (find(i)) res++; } System.out.println(res); } }